diff options
95 files changed, 2336 insertions, 527 deletions
@@ -1,13 +0,0 @@ - -* Sound may not set volumes correctly. - - It is possible that volume of sound effects does not scale properly - with distance from the sound source. It is also possible that sound - effects are cut off at the wrong distance. This needs further - investigation. - -* A small number of Doom bugs are almost impossible to emulate. - - An example of this can be seen in Ledmeister's "Blackbug" demo which - shows a bug that relies on the memory layout of the Doom executable. - @@ -1,3 +1,258 @@ +2011-05-17 23:51:37 fraggle + + Add dependency for INSTALL generation. + +2011-05-17 23:06:22 fraggle + + Detect chex.deh if it is in the same directory as the IWAD file. + +2011-05-14 22:50:46 fraggle + + Fix display of ENDOOM screen. + +2011-05-14 22:47:12 fraggle + + Fix install of screensaver desktop file. + +2011-05-14 22:07:55 fraggle + + Add freedesktop.org desktop files for chocolate-doom, chocolate-setup + (thanks Adrián Chaves Fernández). + +2011-05-14 21:11:26 fraggle + + Convert build system to using the PROGRAM_PREFIX system used on + raven-branch. + +2011-05-08 19:32:02 fraggle + + Update NEWS. + +2011-05-08 19:29:46 fraggle + + Allow IWAD files to be double-clicked in the finder to set the IWAD + configuration. + +2011-05-08 01:31:01 fraggle + + Shut up compiler warnings. + +2011-05-08 00:52:26 fraggle + + Rework OS X launcher package. Include documentation files within the + application bundle and add a help menu with links. Rework .dmg + generation to generate a file with a "fancy" background image and + overall nicer appearance. + +2011-04-26 06:49:53 quasar_te + + Support for Win32 native OPL output when compiled with Microsoft + Visual C++. Confirmed to work with Aureal Vortex AU8830 in Win98SE by + GhostlyDeath. + +2011-04-24 23:22:11 fraggle + + Infer -server when -privateserver is specified (thanks Porsche Monty). + +2011-04-24 22:39:31 fraggle + + Add test button to joystick menu in setup tool (thanks Alexandre + Xavier). + +2011-04-18 23:10:16 fraggle + + Add test hack for simulating Porsche Monty's scanline emulation (see + comment in file). + +2011-04-17 18:33:04 fraggle + + Fix libtextscreen window hotkeys to work when shift is held down / + capslock turned on. Fix a similar problem in-game when typing cheat + codes or using menu hotkeys (thanks Alexandre Xavier). + +2011-04-17 17:53:47 fraggle + + Make Final Doom IWAD labels shorter, so they don't make the launch + windows grow. + +2011-04-11 20:49:45 fraggle + + Allow the shift key to be held down when changing key/mouse/joystick + bindings to prevent bindings to the same key from being cleared + (thanks myk). + +2011-04-09 01:27:13 fraggle + + Fix action area minimum width calculation. + +2011-04-04 21:30:17 fraggle + + Close dropdown list popup windows when clicking outside the window. + +2011-04-04 21:12:59 fraggle + + Fix crash. + +2011-04-04 21:09:42 fraggle + + Fix crash. + +2011-04-04 21:07:07 fraggle + + Change the background color when hovering over widgets. + +2011-04-04 19:40:28 fraggle + + Change setup tool default sampling rate to 44100Hz to match the game + (thanks Alexandre Xavier). + +2011-03-30 20:16:40 fraggle + + Add a symlink hack to work around the fact that OS X doesn't like + paths in MANPATH to contain spaces. + +2011-03-30 20:00:51 fraggle + + On OS X, display a dialog box when exiting with I_Error, like on + Windows. + +2011-03-29 00:48:31 fraggle + + Remove the BUGS file as it doesn't really contain any useful + information. + +2011-03-29 00:39:48 fraggle + + Add vim modeline for text wrapping to documentation text files. + +2011-03-29 00:33:09 fraggle + + Emulate bug with IDMUS cheat when emulating v1.9 (thanks Alexandre + Xavier). + +2011-03-28 22:36:00 fraggle + + Fix OPL MIDI playback when using an empty .mus / .mid file (thanks + Alexandre Xavier). + +2011-03-28 22:32:14 fraggle + + Allow .lmp files to be loaded (and demo files to be played back) that + have long filenames (thanks blzut3). + +2011-03-28 01:24:47 fraggle + + Fix weapon cycling from the shotgun to the chaingun in Doom 1 (thanks + Alexandre Xavier). + +2011-03-28 00:45:53 fraggle + + Scroll faster in reaction to the scroll wheel. + +2011-03-28 00:42:00 fraggle + + Change default sfx/music volume in setup tool to 8, to match the game + (thanks Alexandre Xavier). + +2011-03-22 21:33:17 fraggle + + Switch separator to show "screen mode" or "window size" depending on + whether fullscreen is turned on or not. + +2011-03-22 21:08:04 fraggle + + Fix scrollbars so that clicks scroll the pane to a location that + matches the clicked location. Interpret mousewheel events so that + scroll panes can be scrolled. + +2011-03-22 19:49:31 fraggle + + Reorganise the display settings window. + +2011-03-17 22:54:33 fraggle + + Add back -a option to automake, and remove INSTALL if automake + installs it. + +2011-03-17 22:43:56 fraggle + + Fix up placement of display settings window. + +2011-03-15 22:41:22 fraggle + + Fix NEWS entry to list the full name for Alexandre Xavier. + +2011-03-10 19:47:14 fraggle + + Include Unix manpages in MacOS package, and set MANPATH to point to + them when opening a terminal window. + +2011-03-10 19:45:29 fraggle + + Minor tweaks to MacOS instructions. + +2011-03-10 19:20:10 fraggle + + Minor tweak to INSTALL instructions. + +2011-03-10 19:03:23 fraggle + + Replace the INSTALL file with a template version that is customized to + different platforms. + +2011-03-09 19:02:15 fraggle + + Add null sector dereference emulation code from Prboom+, to fix desync + with CLNJ-506.LMP (thanks entryway). + +2011-03-09 01:06:07 fraggle + + Add support for the alternate version of the Final Doom executable + that fixes the demo loop crash (thanks Porsche Monty, Enjay). + +2011-03-06 20:59:51 fraggle + + Discard very short sound effects and strip lead-in / lead-out samples + that apparently aren't played by Vanilla Doom (thanks Quasar). + +2011-03-03 21:41:51 fraggle + + Fix Visual Studio build (thanks GhostlyDeath). + +2011-02-28 20:48:27 fraggle + + Fix autoadjust of pixel depth in setup tool. + +2011-02-05 16:50:28 fraggle + + Fix bug with libtextscreen where it was not possible to type a '+' + (thanks Alexandre Xavier). + +2011-01-31 01:25:47 fraggle + + When large numbers of screen resolutions are detected, increase the + number of columns in the mode list to fit them all on-screen. Remove + superfluous left-side spacing from the checkbox and radio button + widgets so that the modes can be packed closer together. + +2011-01-23 21:42:09 fraggle + + Fix default joystick buttons in setup tool to match Vanilla (thanks + twipley). + +2011-01-13 20:34:55 fraggle + + In configuration files, use the scan code for right shift, not left + shift, to match Vanilla (thanks AlexXav). + +2011-01-12 23:22:20 fraggle + + Fix menu navigation when using joystick / joypad (thanks AlexXav). + +2011-01-02 18:14:59 fraggle + + Update NEWS and ChangeLog, bump version number. + 2011-01-02 17:45:24 fraggle Remove redundant package version label from top of OS X launcher @@ -172,3 +172,5 @@ this template: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. +# vim: tw=70 + diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 7ad85b7f..00000000 --- a/INSTALL +++ /dev/null @@ -1,173 +0,0 @@ - -Chocolate Doom installation -=========================== - -These are instructions for how to install and set up Chocolate Doom -for play. - -Building Chocolate Doom ------------------------ - -Before you can play Chocolate Doom, you need to compile a binary that -you can run. If you are using Windows or Mac OS X, precompiled -binaries are available on the website for download, and you can skip -this section. - -For compilation, Chocolate Doom requires the following to be installed: - - * A C compiler (gcc is recommended) - * make (GNU make is recommended) - * LibSDL (see http://www.libsdl.org/) - * SDL_mixer (see http://www.libsdl.org/projects/SDL_mixer/) - * SDL_net (see http://www.libsdl.org/projects/SDL_net/) - * Python (optional) - -Follow the standard instructions for installing an autotools-based -package: - - 1. Run './configure' to initialize the package. - 2. Run 'make' to compile the package. - 3. Run 'make install' to install the package. - -Advanced topics such as cross-compilation are beyond the scope of this -document. Please see the GNU autoconf / automake documentation for more -information. - -Obtaining an IWAD file ----------------------- - -To play Doom, you need an IWAD file. This file contains the game data -that is used in gameplay (graphics, sounds, etc). The full versions of -the Doom games are proprietary and need to be bought. The IWAD file -has one of the following names: - - doom1.wad (Shareware Doom) - doom.wad (Registered / Ultimate Doom) - doom2.wad (Doom 2) - tnt.wad (Final Doom: TNT: Evilution) - plutonia.wad (Final Doom: Plutonia Experiment) - chex.wad (Chex Quest) - -If you don't have a copy of the commercial version, you can download -the shareware version (extract the file named doom1.wad): - - * http://www.doomworld.com/idgames/index.php?id=7053 - (idstuff/doom/win95/doom95.zip in your nearest /idgames mirror) - -If you have a commercial version, obtaining the IWAD file may slightly -complicated. The method depends on how you obtained your copy of the -game: - - * There have been several CD-based versions of Doom. Generally, the - IWAD files can be found on the CD and copied off directly. - - * The IWAD files might not be directly available on the CD. Look for - a program named "deice.exe". In the same directory, there should - be a single large file with a numbered extension (eg. - "resource.1"); to extract this, follow the same instructions as for - the floppy disk version (see below). - - * If you have the floppy disk version of Doom, first copy the - contents of all the floppy disks into a directory together. You - will have several large files with numbered extensions. - Concatenate these into a single file, eg. - - (Unix instructions) - cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.exe - - (Windows/DOS instructions) - copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se+5 doom_se.exe - - The resulting file is self-extracting LHA file. If you have a DOS - emulator (such as DOSbox), you can run it to extract the files; - alternatively, you can use the Unix LHA tool to extract the - archive. - - * The Doom games are also available for download on Steam - (http://www.steampowered.com/). To find the IWAD files, look in - your Steam directory, under the "steamapps/common" path. - -Running the game ----------------- - -When you have an IWAD file, install it through one of the following -methods: - - * Under Mac OS X, you can specify the locations of the IWAD files - through the graphical launcher program. Click the "Configure..." - button, and then click "Set..." for each IWAD location to choose - its location. - - * Under Unix, put the file into the /usr/share/games/doom or - /usr/local/share/games/doom directories. - - * Place it in a directory and set the environment variable DOOMWADDIR - to be the path to that directory. - - * Install multiple IWADs into separate directories and set the - environment variable DOOMWADPATH to be a colon-separated list of - directories to search (similar to the Unix PATH environment - variable). - - * Run Chocolate Doom with the '-iwad' command line parameter to - specify the IWAD file to use, eg. - - chocolate-doom -iwad /root/doom2.wad - -Playing with Chex Quest ------------------------ - -Chex Quest is a game based on Doom with some minor modifications that -was distributed with boxes of Chex cereal in 1997. It is possible to -play Chex Quest using Chocolate Doom. To do this, the following files -are needed: - - * The IWAD file 'chex.wad', from the Chex Quest CD. - - * The dehacked patch 'chex.deh', which can be found in the /idgames - repository in utils/exe_edit/patches/chexdeh.zip. - -Copy these files into a directory together and use the '-iwad' command -line parameter to specify the Chex Quest IWAD file: - - chocolate-doom -iwad chex.wad - -Installing upgrades -------------------- - -Chocolate Doom requires a Doom 1.9 IWAD file. Generally, if you -install a recent version of Doom you should automatically have a 1.9 -IWAD. However, if you are installing from a very old CD version or -from floppy disks, you might find you have an older version. - -The most obvious symptom of an out of date IWAD file is that the game -will exit at the title screen before the demo starts, with the message -"Demo is from a different game version!". If this happens, your IWAD -file is out of date and you need to upgrade. - -Id Software released upgrade patches that will update your game to -1.9. The following sites have the patches: - - http://www.doomworld.com/files/patches.shtml - http://www.doom2.net/doom2/utils.html - ftp://ftp.idsoftware.com/idstuff/doom2 - -As the patches are binary patches that run as DOS executables, you -will need a DOS emulator (such as DOSBox) to install them. - -Music support -------------- - -Support for Doom's MIDI music is available through Timidity: - - http://timidity.sourceforge.net/ - -A good set of patches for Timidity is the eawpats collection, which can -be found here: - - http://www.doomworld.com/idgames/index.php?id=13928 - (Doom idgames archive, /sounds/eawpats.zip) - -If compiling from source, be sure to compile and install timidity -before installing SDL_mixer. - diff --git a/Makefile.am b/Makefile.am index 09fc5868..46c9dec8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,36 +31,32 @@ CODEBLOCKS_FILES= \ codeblocks/setup.cbp \ codeblocks/setup-res.rc -DATA_FILES= \ - data/README \ - data/doom.ico \ - data/doom8.ico \ - data/doom.png \ - data/setup.ico \ - data/setup8.ico \ - data/setup.png \ - data/convert-icon +DOC_FILES= \ + CMDLINE \ + README \ + README.OPL \ + NEWS \ + ChangeLog \ + NOT-BUGS EXTRA_DIST= \ $(AUX_DIST_GEN) \ $(MSVC_FILES) \ $(CODEBLOCKS_FILES) \ - $(DATA_FILES) \ + $(DOC_FILES) \ .lvimrc \ - config.h \ - CMDLINE \ HACKING \ - README.OPL \ TODO \ - BUGS \ - NOT-BUGS \ rpm.spec +docdir=$(prefix)/share/doc/@PACKAGE@ +doc_DATA=$(DOC_FILES) + MAINTAINERCLEANFILES = $(AUX_DIST_GEN) docdir=$(prefix)/share/doc/@PACKAGE@ -SUBDIRS=wince textscreen opl pcsound src man +SUBDIRS=wince textscreen opl pcsound data src man DIST_SUBDIRS=pkg $(SUBDIRS) @@ -71,5 +67,8 @@ noinst_DATA=CMDLINE CMDLINE : src/ ./man/docgen -p man/CMDLINE.template src/ > $@ +INSTALL : man/INSTALL.template man/simplecpp + ./man/simplecpp < man/INSTALL.template > $@ + endif @@ -1,22 +1,86 @@ -1.6.0 (2011-??-??): +1.6.0 (2011-05-17): + + * The instructions in the INSTALL file are now customized for + different platforms, and each binary package contains a version + with instructions specific to the platform that it is + targetting. This should help to avoid confusion that some + users have reported experiencing. + * The display settings window in the setup tool has been + reorganised to a better arrangement. + * It is now possible to load .lmp files (and play back demos) + with long filenames (thanks blzut3). + * In the setup tool, it is now possible to hold down shift when + changing key/mouse/joystick bindings to prevent other bindings + to the same key from being cleared (thanks myk). + * The joystick menu in the setup tool now has a test button + (thanks Alexandre Xavier). + * Specifying the -privateserver option implies -server (thanks + Porsche Monty). + * The Mac OS X .dmg package now has a background and looks generally + more polished. + * In Mac OS X, it is now possible to simply double click an IWAD + file in the Finder to configure its location within the launcher. + * Freedesktop.org desktop files are now installed for Doom and + the setup tool, which will appear in the main menu on desktop + environments such as Gnome and KDE (thanks Adrián Chaves + Fernández). + * The Chex Quest dehacked patch (chex.deh) will now be detected + if it is in the same directory as the IWAD file. Compatibility: + * Added support for the alternate version of the Final Doom + executable included in some later versions of the Id Anthology. + This version fixed the demo loop crash that occurred with the + "original" Final Doom executable. + + This executable can be selected on the command line with + -gameversion final2. It has been made the default when playing + with the Final Doom IWADs (the original behavior can be + selected with -gameversion final). (thanks Porsche Monty, + Enjay). * Very short sound effects are not played, to better emulate the behavior of DMX in Vanilla Doom (thanks to Quasar for help in investigating this). + * The null sector dereference emulation code has been imported + from Prboom+ - this fixes a desync with CLNJ-506.LMP (thanks + entryway). + * The IDMUS cheat doesn't work when emulating the v1.9 executable + (thanks Alexandre Xavier). Bugs fixed: * Menu navigation when using joystick/joypad (thanks Alexandre Xavier). * For configuration file value for shift keys, use scan code for - right shift, not left shift (thanks AlexXav). + right shift, not left shift (thanks Alexandre Xavier). * Default joystick buttons for the setup tool now match Vanilla (thanks twipley). * Visual Studio project files work again (thanks GhostlyDeath). + * The default sfx/music volume set by the setup tool is now 8 + instead of 15, matching the game itself. (thanks Alexandre + Xavier). + * Weapon cycling from the shotgun to the chaingun in Doom 1 now + works properly (thanks Alexandre Xavier). + * MIDI playback that locked up when using an empty MUS / MIDI + file (thanks Alexandre Xavier). + * Default sampling rate used by setup tool changed to 44100Hz, to + match the game default (thanks Alexandre Xavier). + * Cheat codes and menu hot keys now work when shift is held down + or capslock turned on (thanks Alexandre Xavier). libtextscreen: + * The background on GUI controls now lights up when hovering over + them, so that it is more obvious what you are selecting. * It is now possible to type a '+' in input boxes (thanks Alexandre Xavier). + * It is possible to use the mouse wheel to scroll through scroll + panes. + * Clicking on scroll bars now moves the scroll handle to a + matching location. + * Clicking outside a dropdown list popup window now dismisses the + window. + * Window hotkeys that are an alphabetical letter now work when + shift is held down or capslock turned on (thanks Alexandre + Xavier). 1.5.0 (2011-01-02): @@ -623,3 +687,5 @@ 0.0.1 (2005-09-07): First beta release +# vim: tw=70 + @@ -31,29 +31,6 @@ upgrade. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -== Game exits in demo loop when playing Final Doom == - -When playing with the Final Doom IWAD files (tnt.wad, plutonia.wad), -if you leave the game at the title screen to play through the demo -loop, it will eventually exit with the following error message: - - W_GetNumForName: demo4 not found! - -This is the same behavior as the Vanilla executables that were -bundled with Final Doom. When Ultimate Doom was developed, a fourth -demo was added to the demo loop, and this change was retained in the -Final Doom version of the executable. However, the Final Doom IWADs -do not include a fourth demo, so the game crashes. - -One way to work around this problem is to make the game emulate the -original (pre-Ultimate Doom) v1.9 executable. To do this, add the -command line argument "-gameversion 1.9" when running the game. -However, be aware this version does have some subtle differences that -will affect the playback of Final Doom demos (lost soul bouncing, -teleport behavior). - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - == Game exits when accessing the options menu == The game may exit with the message "Bad V_DrawPatch" when accessing @@ -133,3 +110,20 @@ More information can be found here: http://rome.ro/lee_killough/editing/visplane.shtml +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +== IDMUS## cheat doesn't work with shareware/registered Doom IWADs == + +The IDMUS cheat allows the in-game music to be changed. However, in +the original v1.9 this cheat didn't work properly when playing with +the Doom 1 (shareware and registered) IWADs. This bug was fixed in +the Ultimate Doom and Final Doom executables. + +Chocolate Doom emulates this bug. When playing with the shareware or +registered Doom IWADs, the IDMUS cheat therefore does not work +properly. If you are playing with the Ultimate Doom IWAD, the +Ultimate Doom executable is emulated by default, so the cheat works +properly. + +# vim: tw=70 + @@ -65,10 +65,11 @@ Here are some examples: You are encouraged to sign up and contribute any useful information you may have regarding the port! - * Chocolate Doom is not perfect. See the BUGS file for a list of - known issues. Because of the nature of the project, you may also - encounter Vanilla Doom bugs; these are intentionally present; see - the NOT-BUGS file for more information. + * Chocolate Doom is not perfect. Although it aims to accurately + emulate Vanilla Doom, some of the behavior of Vanilla Doom can be + very difficult to reproduce. Because of the nature of the project, + you may also encounter Vanilla Doom bugs; these are intentionally + present; see the NOT-BUGS file for more information. New bug reports can be submitted to the Chocolate Doom bug tracker on Sourceforge. See: @@ -85,3 +86,5 @@ Here are some examples: * Please send any feedback, questions or suggestions to fraggle@gmail.com. Thanks! +# vim: tw=70 + @@ -105,3 +105,5 @@ on startup: There is no native OPL backend for FreeBSD yet. Sorry! +# vim: tw=70 + @@ -54,3 +54,5 @@ Other tasks: * Get a better software OPL emulator * DMXOPTIONS opl3/phase option support. +# vim: tw=70 + @@ -1,12 +1,26 @@ #!/bin/sh +if [ -e INSTALL ]; then + have_INSTALL=true +else + have_INSTALL=false +fi + mkdir autotools aclocal autoheader -automake -a -c +automake -ac autoconf automake +# The INSTALL file is autogenerated, so it isn't stored in version control. +# As the file isn't present, automake's -a option will install generic +# install instructions. So remove INSTALL if automake installed one. + +if ! $have_INSTALL; then + rm -f INSTALL +fi + ./configure "$@" diff --git a/codeblocks/config.h b/codeblocks/config.h index 9026d398..e8c2f95d 100644 --- a/codeblocks/config.h +++ b/codeblocks/config.h @@ -9,19 +9,22 @@ #define PACKAGE_NAME "Chocolate Doom" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Chocolate Doom 1.5.0" +#define PACKAGE_STRING "Chocolate Doom 1.6.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "chocolate-doom" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.5.0" +#define PACKAGE_VERSION "1.6.0" + +/* Change this when you create your awesome forked version */ +#define PROGRAM_PREFIX "chocolate-" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "1.5.0" +#define VERSION "1.6.0" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ diff --git a/codeblocks/game-res.rc b/codeblocks/game-res.rc index beef1242..2a3a7ac7 100644 --- a/codeblocks/game-res.rc +++ b/codeblocks/game-res.rc @@ -1,21 +1,21 @@ 1 ICON "../data/doom.ico" 1 VERSIONINFO -PRODUCTVERSION 1,5,0,0 -FILEVERSION 1,5,0,0 +PRODUCTVERSION 1,6,0,0 +FILEVERSION 1,6,0,0 FILETYPE 1 { BLOCK "StringFileInfo" { BLOCK "040904E4" { - VALUE "FileVersion", "1.5.0" - VALUE "FileDescription", "1.5.0" + VALUE "FileVersion", "1.6.0" + VALUE "FileDescription", "1.6.0" VALUE "InternalName", "Chocolate-Doom" VALUE "CompanyName", "Chocolate-Doom" VALUE "LegalCopyright", "GNU General Public License" VALUE "ProductName", "Chocolate-Doom" - VALUE "ProductVersion", "1.5.0" + VALUE "ProductVersion", "1.6.0" } } } diff --git a/codeblocks/setup-res.rc b/codeblocks/setup-res.rc index b3812a74..4735cbd9 100644 --- a/codeblocks/setup-res.rc +++ b/codeblocks/setup-res.rc @@ -3,21 +3,21 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "setup-manifest.xml" 1 VERSIONINFO -PRODUCTVERSION 1,5,0,0 -FILEVERSION 1,5,0,0 +PRODUCTVERSION 1,6,0,0 +FILEVERSION 1,6,0,0 FILETYPE 1 { BLOCK "StringFileInfo" { BLOCK "040904E4" { - VALUE "FileVersion", "1.5.0" + VALUE "FileVersion", "1.6.0" VALUE "FileDescription", "Chocolate-Doom Setup" VALUE "InternalName", "chocolate-setup" VALUE "CompanyName", "fraggle@gmail.com" VALUE "LegalCopyright", "GNU General Public License" VALUE "ProductName", "Chocolate-Doom Setup" - VALUE "ProductVersion", "1.5.0" + VALUE "ProductVersion", "1.6.0" } } } diff --git a/configure.in b/configure.in index c100d7cf..1b0650e3 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ -AC_INIT(Chocolate Doom, 1.5.0, fraggle@gmail.com, chocolate-doom) +AC_INIT(Chocolate Doom, 1.6.0, fraggle@gmail.com, chocolate-doom) PACKAGE_SHORTDESC="Conservative Doom source port" -PACKAGE_COPYRIGHT="Copyright (C) 1993-2010" +PACKAGE_COPYRIGHT="Copyright (C) 1993-2011" PACKAGE_LICENSE="GNU General Public License, version 2" PACKAGE_MAINTAINER="Simon Howard" PACKAGE_URL="http://www.chocolate-doom.org/" @@ -153,7 +153,9 @@ pkg/config.make pkg/osx/Info-gnustep.plist pkg/osx/Info.plist rpm.spec +data/Makefile src/Makefile +src/doom.desktop src/doom-screensaver.desktop src/doom/Makefile src/heretic/Makefile @@ -161,6 +163,7 @@ src/hexen/Makefile src/resource.rc src/setup-res.rc src/setup/Makefile +src/setup/setup.desktop src/setup/setup-manifest.xml textscreen/Makefile textscreen/examples/Makefile diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 00000000..a76bba93 --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,4 @@ +Makefile.in +Makefile +*-doom.png +*-setup.png diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 00000000..dccb51a3 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,21 @@ + +EXTRA_DIST= \ + README \ + doom.ico \ + doom8.ico \ + doom.png \ + setup.ico \ + setup8.ico \ + setup.png \ + convert-icon + +iconsdir = $(prefix)/share/icons +icons_DATA = @PROGRAM_PREFIX@doom.png \ + @PROGRAM_PREFIX@setup.png + +@PROGRAM_PREFIX@doom.png : doom.png + cp $^ $@ + +@PROGRAM_PREFIX@setup.png : setup.png + cp $^ $@ + diff --git a/man/INSTALL.template b/man/INSTALL.template new file mode 100644 index 00000000..19d3c88d --- /dev/null +++ b/man/INSTALL.template @@ -0,0 +1,253 @@ + +Chocolate Doom installation +=========================== + +These are instructions for how to install and set up Chocolate Doom +for play. + +#ifn PRECOMPILED +Building Chocolate Doom +----------------------- + +Before you can play Chocolate Doom, you need to compile a binary that +you can run. For compilation, Chocolate Doom requires the following +to be installed: + + * A C compiler (gcc is recommended) + * make (GNU make is recommended) + * LibSDL (see http://www.libsdl.org/) + * SDL_mixer (see http://www.libsdl.org/projects/SDL_mixer/) + * SDL_net (see http://www.libsdl.org/projects/SDL_net/) + * Python (optional) + +Follow the standard instructions for installing an autotools-based +package: + + 1. Run './configure' to initialize the package. + 2. Run 'make' to compile the package. + 3. Run 'make install' to install the package. + +An automated build script is available that installs the necessary +dependencies and builds the source code automatically. See the build +instructions on the website. + +Advanced topics such as cross-compilation are beyond the scope of this +document. Please see the GNU autoconf / automake documentation for more +information. + +#endif +Obtaining an IWAD file +---------------------- + +To play Doom, you need an IWAD file. This file contains the game data +(graphics, sounds, etc). The full versions of the Doom games are +proprietary and need to be bought. The IWAD file has one of the +following names: + + doom1.wad (Shareware Doom) + doom.wad (Registered / Ultimate Doom) + doom2.wad (Doom 2) + tnt.wad (Final Doom: TNT: Evilution) + plutonia.wad (Final Doom: Plutonia Experiment) + chex.wad (Chex Quest) + +If you don't have a copy of a commercial version, you can download +the shareware version (extract the file named doom1.wad): + + * http://www.doomworld.com/idgames/index.php?id=7053 + (idstuff/doom/win95/doom95.zip in your nearest /idgames mirror) + +If you have a commercial version, obtaining the IWAD file is usually +straightforward. The method depends on how you obtained your copy of +the game: + +#if _WIN32 + * The Doom games are available to buy for download on Steam + (http://www.steampowered.com/). Chocolate Doom will autodetect + IWADs installed by Steam and you do not need to do anything. +#else + * The Doom games are available to buy for download on Steam + (http://www.steampowered.com/). To find the IWAD files on a + Windows system, look in the Steam directory (usually within + "Program Files"), under the "steamapps/common" path. +#endif + + * There have been several CD-based versions of Doom. Generally, the + IWAD files can be found on the CD and copied off directly. + +#if _WIN32 + * If the IWAD files are not directly available on the CD, or you have + a floppy disk version, you will need to run the install program to + install the game to your hard disk. As the installer is DOS-based, + you may not be able to do this on 64-bit versions of Windows. In + this case, the best suggestion is to use a DOS emulator (such as + DOSbox) to run the installer. +#else + * If the IWAD files are not directly available on the CD, or you have + a floppy disk version, installation is more difficult. The best + suggestion is to use a DOS emulator (such as DOSbox) to run the + installer. +#endif + + * As an alternative to using an emulator, it is possible to extract + the files manually. On the install disk(s), you will find several + files with numbered extensions (with CD versions there may be a + single large file with the extension .1, eg. "resource.1"). + + From the command line it is possible to combine these files into a + single large file, using a command similar to the following: + +#if _WIN32 + copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se.5 doom_se.lha +#else + cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.lha +#endif + + The resulting file is an LHA archive file, and it can be extracted + using an LHA archive tool (there is one available for almost every + operating system). + +Running the game +---------------- + +#if __MACOSX__ +Once you have an IWAD file, you can specify its location within the +graphical launcher program. Click the "Configure..." button, and then +click "Set..." for each IWAD to choose its location. From the main +launcher dialog you can then choose which game you want to play and +click the "Launch" button to start the game. + +If you are an advanced user and like to run Doom from the command +line, you can use the "Command Prompt..." menu item to open a Terminal +window. The DOOMWADPATH environment variable is preconfigured +to point to the locations of the IWAD files set within the launcher. +You can launch the game with a specific IWAD file by typing, for +example: + + chocolate-doom -iwad tnt.wad +#else +Chocolate Doom needs to know where to find your IWAD file. To do this, +do one of the following: + +#if _WIN32 + * Within Explorer, simply place the IWAD file in the same folder as + the Chocolate Doom files, and double-click chocolate-doom.exe. + + * Run Chocolate Doom from the command prompt with the '-iwad' command + line parameter to specify the IWAD file to use, eg. + + chocolate-doom -iwad c:\games\doom2.wad + + * Set the environment variable DOOMWADDIR to the location of a + directory containing your IWAD files. + + * If you have multiple IWADs in different directories, set the + environment variable DOOMWADPATH to be a semicolon-separated list + of directories to search (similar to the PATH environment + variable). +#else + * Run Chocolate Doom from the Unix console with the '-iwad' command + line parameter to specify the IWAD file to use, eg. + + chocolate-doom -iwad /root/doom2.wad + + * Put the file into one of the following directories: + + /usr/share/games/doom + /usr/local/share/games/doom + + * Set the environment variable DOOMWADDIR to specify the path to a + directory containing your IWAD files. + + * If you have multiple IWADs in different directories, set the + environment variable DOOMWADPATH to be a colon-separated list of + directories to search (similar to the Unix PATH environment + variable). +#endif +#endif + +Playing with Chex Quest +----------------------- + +Chex Quest is a game based on Doom with some minor modifications that +was distributed with boxes of Chex cereal in 1997. It is possible to +play Chex Quest using Chocolate Doom. To do this, the following files +are needed: + + * The IWAD file 'chex.wad', from the Chex Quest CD. + + * The dehacked patch 'chex.deh', which can be found here: + http://www.doomworld.com/idgames/?id=15420 + (utils/exe_edit/patches/chexdeh.zip in your nearest /idgames mirror) + +Copy these files into a directory together and use the '-iwad' command +line parameter to specify the Chex Quest IWAD file: + + chocolate-doom -iwad chex.wad + +Installing upgrades +------------------- + +Chocolate Doom requires a version 1.9 IWAD file. Generally, if you +install a recent version of Doom you should have a version 1.9 IWAD. +However, if you are installing from a very old CD version or from +floppy disks, you might find you have an older version. + +The most obvious symptom of an out of date IWAD file is that the game +will exit at the title screen before the demo starts, with the message +"Demo is from a different game version!". If this happens, your IWAD +file is out of date and you need to upgrade. + +Id Software released upgrade patches that will update your game to +version 1.9. The following sites have the patches: + + http://www.doomworld.com/files/patches.shtml + http://www.doom2.net/doom2/utils.html + ftp://ftp.idsoftware.com/idstuff/doom2 + +#if _WIN32 +As the patches are binary patches that run as DOS executables, on +recent 64-bit versions of Windows you will need to use a DOS emulator +(such as DOSBox) to run them. +#else +As the patches are binary patches that run as DOS executables, you +will need to use a DOS emulator (such as DOSBox) to run them. +#endif + +Music support +------------- + +Chocolate Doom includes OPL emulation code that accurately reproduces +the way that the in-game music sounded under DOS when using an +Adlib/Soundblaster card. This is, however, not to everyone's taste. + +#if _WIN32 +Better quality MIDI playback is possible by using Windows' native +MIDI synthesizer that is part of the operating system. Select "Native +MIDI" within the sound dialog in the setup tool. + +#endif +#if __MACOSX__ +High quality MIDI playback is possible by using Mac OS X's native MIDI +synthesizer that is part of the operating system. Select "Native MIDI" +within the sound dialog in the setup tool. + +#endif +As an alternative it is possible to use Timidity for high quality MIDI +playback: + + http://timidity.sourceforge.net/ + +A good set of patches for Timidity is the eawpats collection, which can +be found here: + + http://www.doomworld.com/idgames/index.php?id=13928 + (Doom idgames archive, /sounds/eawpats.zip) + +#ifn PRECOMPILED +When compiling from source, be sure to compile and install timidity +before installing SDL_mixer. +#endif + +# vim: tw=70 + diff --git a/man/Makefile.am b/man/Makefile.am index 698c0862..618c0bde 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,6 +1,8 @@ MANPAGE_GEN_FILES=manpage.template docgen default.cfg.template extra.cfg.template +docdir=$(prefix)/share/doc/@PACKAGE@ + if HAVE_PYTHON man_MANS=chocolate-doom.6 \ @@ -9,6 +11,8 @@ man_MANS=chocolate-doom.6 \ default.cfg.5 \ $(PACKAGE).cfg.5 +nodist_doc_DATA=INSTALL + chocolate-doom.6: ../src $(MANPAGE_GEN_FILES) ./docgen -m manpage.template ../src > $@ @@ -18,9 +22,14 @@ default.cfg.5: ../src default.cfg.template $(PACKAGE).cfg.5: ../src extra.cfg.template ./docgen -m extra.cfg.template -c $(PACKAGE).cfg ../src > $@ +INSTALL: INSTALL.template + ./simplecpp -DPRECOMPILED < INSTALL.template > $@ + endif EXTRA_DIST = $(man_MANS) $(MANPAGE_GEN_FILES) \ wikipages \ - CMDLINE.template + CMDLINE.template \ + INSTALL.template \ + simplecpp diff --git a/man/simplecpp b/man/simplecpp new file mode 100755 index 00000000..d277f278 --- /dev/null +++ b/man/simplecpp @@ -0,0 +1,211 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Contributors to the Freedoom project. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the freedoom project nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# simple cpp-style preprocessor +# +# Understands: +# +# #define NAME +# +# Set an option +# You can use -D on the command line too +# +# #undef NAME +# +# Unset an option if it is set +# +# #if .. #endif / #ifdef .. #endif +# +# Specify a list of options set, eg #ifdef DOOM2 || ULTDOOM || SHAREWARE +# The block is only displayed if one of the options is set +# +# #ifn .. #endif / #ifndef .. #endif +# +# Similarly specify a list of options +# The block is displayed if none of the options are set +# +# #include "filename" +# +# include the contents of a file + +import sys +import re + +debug = False +defines = {} + +command_re = re.compile("\#(\w+)(\s+(.*))?") +include_re = re.compile("\s*\"(.*)\"\s*") + +def debug_msg(message): + if debug: + sys.stderr.write(message) + +# Parse command line options + +def parse_cmdline(): + for arg in sys.argv[1:]: + if arg.startswith("-D"): + name = arg[2:] + defines[name] = True + +def parse_stream(stream): + result = read_block(stream, False) + + if result is not None: + raise Exception("Mismatched #if in '%s'" % stream.name) + +def parse_file(filename): + f = open(filename) + + try: + parse_stream(f) + finally: + f.close() + +# #include + +def cmd_include(arg): + # Extract the filename + + match = include_re.match(arg) + + if not match: + raise Exception("Invalid 'include' command") + + filename = match.group(1) + + # Open the file and process it + + parse_file(filename) + +# #define + +def cmd_define(arg): + defines[arg] = True + +# #undef + +def cmd_undef(arg): + if arg in defines: + del defines[arg] + +# #ifdef/#ifndef + +def cmd_ifdef(arg, command, stream, ignore): + + # Get the define name + name = arg.strip() + + debug_msg("%s %s >\n" % (command, arg)) + + # Should we ignore the contents of this block? + + sub_ignore = (name not in defines) + + if "n" in command: + sub_ignore = not sub_ignore + + # Parse the block + + result = read_block(stream, ignore or sub_ignore) + + debug_msg("%s %s < (%s)\n" % (command, arg, result)) + + # There may be a second "else" block to parse: + + if result == "else": + debug_msg("%s %s else >\n" % (command, arg)) + result = read_block(stream, ignore or (not sub_ignore)) + debug_msg("%s %s else < (%s)\n" % (command, arg, result)) + + # Should end in an endif: + + if result != "endif": + raise Exception("'if' block did not end in an 'endif'") + +commands = { + "include" : cmd_include, + "define" : cmd_define, + "undef" : cmd_undef, + "if" : cmd_ifdef, + "ifdef" : cmd_ifdef, + "ifn" : cmd_ifdef, + "ifndef" : cmd_ifdef, +} + +# Recursive block reading function +# if 'ignore' argument is 1, contents are ignored + +def read_block(stream, ignore): + + for line in stream: + + # Remove newline + + line = line[0:-1] + + # Check if this line has a command + + match = command_re.match(line) + + if match: + command = match.group(1) + arg = match.group(3) + + if command == "else" or command == "endif": + return command + elif command not in commands: + raise Exception("Unknown command: '%s'" % \ + command) + + # Get the callback function. + + func = commands[command] + + # Invoke the callback function. #ifdef commands + # are a special case and need extra arguments. + # Other commands are only executed if we are not + # ignoring this block. + + if func == cmd_ifdef: + cmd_ifdef(arg, command=command, + stream=stream, + ignore=ignore) + elif not ignore: + func(arg) + else: + if not ignore: + print(line) + +parse_cmdline() +parse_stream(sys.stdin) + diff --git a/msvc/config.h b/msvc/config.h index d91bd23b..5d966951 100644 --- a/msvc/config.h +++ b/msvc/config.h @@ -11,16 +11,19 @@ #define PACKAGE_NAME "Chocolate Doom" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Chocolate Doom 1.5.0" +#define PACKAGE_STRING "Chocolate Doom 1.6.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "chocolate-doom" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.5.0" +#define PACKAGE_VERSION "1.6.0" + +/* Change this when you create your awesome forked version */ +#define PROGRAM_PREFIX "chocolate-" /* Version number of package */ -#define VERSION "1.5.0" +#define VERSION "1.6.0" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ diff --git a/msvc/win32.rc b/msvc/win32.rc index 3371d993..3f0c361c 100644 --- a/msvc/win32.rc +++ b/msvc/win32.rc @@ -32,21 +32,21 @@ #endif
1 VERSIONINFO
-PRODUCTVERSION 1,5,0,0
-FILEVERSION 1,5,0,0
+PRODUCTVERSION 1,6,0,0
+FILEVERSION 1,6,0,0
FILETYPE 1
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
- VALUE "FileVersion", "1.5.0"
- VALUE "FileDescription", "Chocolate Doom 1.5.0"
+ VALUE "FileVersion", "1.6.0"
+ VALUE "FileDescription", "Chocolate Doom 1.6.0"
VALUE "InternalName", "chocolate-doom"
VALUE "CompanyName", "fraggle@gmail.com"
VALUE "LegalCopyright", "GNU General Public License"
VALUE "ProductName", "Chocolate Doom"
- VALUE "ProductVersion", "1.5.0"
+ VALUE "ProductVersion", "1.6.0"
END
END
END
diff --git a/opl/opl_win32.c b/opl/opl_win32.c index 29df3643..277ce76c 100644 --- a/opl/opl_win32.c +++ b/opl/opl_win32.c @@ -72,8 +72,35 @@ static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) ); } -// TODO: MSVC version -// #elif defined(_MSC_VER) && defined(_M_IX6) ... +// haleyjd 20110417: MSVC version +#elif defined(_MSC_VER) && defined(_M_IX86) + +static unsigned int OPL_Win32_PortRead(opl_port_t port) +{ + unsigned char result; + opl_port_t dst_port = opl_port_base + port; + + __asm + { + mov edx, dword ptr [dst_port] + in al, dx + mov byte ptr [result], al + } + + return result; +} + +static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) +{ + opl_port_t dst_port = opl_port_base + port; + + __asm + { + mov edx, dword ptr [dst_port] + mov al, byte ptr [value] + out dx, al + } +} #else diff --git a/pkg/Makefile.am b/pkg/Makefile.am index 438a870a..538b9e1e 100644 --- a/pkg/Makefile.am +++ b/pkg/Makefile.am @@ -7,10 +7,13 @@ osx/Resources/wadfile.icns \ osx/Resources/wadfile.png \ osx/Resources/launcher.nib/designable.nib \ osx/Resources/launcher.nib/keyedobjects.nib \ +osx/disk/dir.DS_Store \ +osx/disk/background.png \ osx/GNUmakefile \ osx/Info.plist.in osx/Info-gnustep.plist.in \ osx/PkgInfo \ osx/cp-with-libs \ +osx/dmgfix \ osx/main.m \ osx/AppController.m osx/AppController.h \ osx/Execute.m osx/Execute.h \ diff --git a/pkg/config.make.in b/pkg/config.make.in index 27e44bd8..8f94f945 100644 --- a/pkg/config.make.in +++ b/pkg/config.make.in @@ -22,9 +22,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ DOC_FILES = README \ COPYING \ ChangeLog \ - INSTALL \ NEWS \ - BUGS \ NOT-BUGS \ CMDLINE \ TODO diff --git a/pkg/osx/AppController.m b/pkg/osx/AppController.m index a26a7c9e..ba8dae9b 100644 --- a/pkg/osx/AppController.m +++ b/pkg/osx/AppController.m @@ -83,6 +83,14 @@ { NSString *extension; + // This may be an IWAD. If so, add it to the IWAD configuration; + // don't add it like a PWAD. + + if ([self->launcherManager addIWADPath: fileName]) + { + return YES; + } + // If this is the first file added, clear out the existing // command line. This allows us to select multiple files // in the finder and open them all together (for TCs, etc). diff --git a/pkg/osx/Execute.h b/pkg/osx/Execute.h index 2098be8a..79591f64 100644 --- a/pkg/osx/Execute.h +++ b/pkg/osx/Execute.h @@ -26,6 +26,7 @@ void SetProgramLocation(const char *path); void ExecuteProgram(const char *executable, const char *iwad, const char *args); void OpenTerminalWindow(const char *doomwadpath); +void OpenDocumentation(const char *filename); #endif /* #ifndef LAUNCHER_EXECUTE_H */ diff --git a/pkg/osx/Execute.m b/pkg/osx/Execute.m index 608443e2..0dcfbb7c 100644 --- a/pkg/osx/Execute.m +++ b/pkg/osx/Execute.m @@ -175,6 +175,19 @@ void OpenTerminalWindow(const char *doomwadpath) fprintf(stream, "#!/bin/sh\n"); //fprintf(stream, "set -x\n"); fprintf(stream, "PATH=\"%s:$PATH\"\n", executable_path); + + // MANPATH is set to point to the directory within the bundle that + // contains the Unix manpages. However, the bundle name or path to + // it can contain a space, and OS X doesn't like this! As a + // workaround, create a symlink in /tmp to point to the real directory, + // and put *this* in MANPATH. + + fprintf(stream, "rm -f \"/tmp/%s.man\"\n", PACKAGE_TARNAME); + fprintf(stream, "ln -s \"%s/man\" \"/tmp/%s.man\"\n", + executable_path, PACKAGE_TARNAME); + fprintf(stream, "MANPATH=\"/tmp/%s.man:$(manpath)\"\n", PACKAGE_TARNAME); + fprintf(stream, "export MANPATH\n"); + fprintf(stream, "DOOMWADPATH=\"%s\"\n", doomwadpath); fprintf(stream, "export DOOMWADPATH\n"); fprintf(stream, "rm -f \"%s\"\n", TEMP_SCRIPT); @@ -206,3 +219,13 @@ void OpenTerminalWindow(const char *doomwadpath) withApplication: @"Terminal"]; } +void OpenDocumentation(const char *filename) +{ + NSString *path; + + path = [NSString stringWithFormat: @"%s/Documentation/%s", + executable_path, filename]; + + [[NSWorkspace sharedWorkspace] openFile: path]; +} + diff --git a/pkg/osx/GNUmakefile b/pkg/osx/GNUmakefile index aa31daf4..cf8c42fc 100644 --- a/pkg/osx/GNUmakefile +++ b/pkg/osx/GNUmakefile @@ -20,9 +20,17 @@ ifndef GNUSTEP_MAKEFILES # DMG file containing package: -$(DMG) : $(STAGING_DIR) +$(DMG) : tmp.dmg rm -f $@ - hdiutil create -volname "$(PACKAGE_STRING)" -srcdir $(STAGING_DIR) $@ + ./dmgfix "$(realpath tmp.dmg)" "$(PACKAGE_STRING)" "$(PACKAGE_NAME).app" + hdiutil convert -format UDZO -o $@ tmp.dmg + rm -f tmp.dmg + +tmp.dmg : $(STAGING_DIR) + rm -f $@ + hdiutil makehybrid -hfs -hfs-volume-name "$(PACKAGE_STRING)" \ + -hfs-openfolder $(STAGING_DIR) $(STAGING_DIR) \ + -o tmp.dmg endif @@ -46,12 +54,13 @@ APP_BIN_DIR=$(APP_DIR)/Contents/MacOS SRC_INFO_PLIST=Info.plist endif +APP_DOC_DIR=$(APP_BIN_DIR)/Documentation +APP_DOC_RELDIR=$(patsubst $(STAGING_DIR)/%,%,$(APP_DOC_DIR)) + $(STAGING_DIR): launcher $(TOPLEVEL_DOCS) rm -rf $(STAGING_DIR) mkdir $(STAGING_DIR) - cp $(TOPLEVEL_DOCS) "$(STAGING_DIR)" - mkdir -p "$(APP_TOP_DIR)" cp -R Resources "$(APP_TOP_DIR)" cp PkgInfo "$(APP_TOP_DIR)" @@ -59,6 +68,13 @@ $(STAGING_DIR): launcher $(TOPLEVEL_DOCS) mkdir -p "$(APP_BIN_DIR)" + mkdir -p "$(APP_DOC_DIR)" + cp $(TOPLEVEL_DOCS) "$(APP_DOC_DIR)" + + ln -s "$(APP_DOC_RELDIR)/COPYING" "$(STAGING_DIR)/Software License" + ln -s "$(APP_DOC_RELDIR)/README" "$(STAGING_DIR)/README" + ln -s /Applications "$(STAGING_DIR)" + cp launcher "$(APP_BIN_DIR)" $(STRIP) "$(APP_BIN_DIR)/launcher" @@ -71,8 +87,18 @@ $(STAGING_DIR): launcher $(TOPLEVEL_DOCS) ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)" $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup" + $(TOPLEVEL)/man/simplecpp -DPRECOMPILED -D__MACOSX__ \ + < $(TOPLEVEL)/man/INSTALL.template \ + > "$(APP_DOC_DIR)/INSTALL" + find $(STAGING_DIR) -name .svn -delete -exec rm -rf {} \; || true + mkdir -p "$(APP_BIN_DIR)/man/man5" "$(APP_BIN_DIR)/man/man6" + cp $(TOPLEVEL)/man/*.5 "$(APP_BIN_DIR)/man/man5" + cp $(TOPLEVEL)/man/*.6 "$(APP_BIN_DIR)/man/man6" + cp disk/dir.DS_Store $(STAGING_DIR)/.DS_Store + cp disk/background.png $(STAGING_DIR)/background.png + clean : launcher_clean rm -f $(DMG) rm -rf $(STAGING_DIR) diff --git a/pkg/osx/IWADController.h b/pkg/osx/IWADController.h index fef28918..2f691f69 100644 --- a/pkg/osx/IWADController.h +++ b/pkg/osx/IWADController.h @@ -51,6 +51,7 @@ - (char *) doomWadPath; - (void) setEnvironment; - (const char *) getGameName; +- (BOOL) addIWADPath: (NSString *) path; @end diff --git a/pkg/osx/IWADController.m b/pkg/osx/IWADController.m index 6cab7ff2..b420d59d 100644 --- a/pkg/osx/IWADController.m +++ b/pkg/osx/IWADController.m @@ -376,5 +376,44 @@ static NSString *IWADFilenames[NUM_IWAD_TYPES + 1] = //free(env); } +// Examine a path to a WAD and determine whether it is an IWAD file. +// If so, it is added to the IWAD configuration, and true is returned. + +- (BOOL) addIWADPath: (NSString *) path +{ + IWADLocation *iwadList[NUM_IWAD_TYPES]; + NSArray *pathComponents; + NSString *filename; + unsigned int i; + + [self getIWADList: iwadList]; + + // Find an IWAD file that matches the filename in the path that we + // have been given. + + pathComponents = [path pathComponents]; + filename = [pathComponents objectAtIndex: [pathComponents count] - 1]; + + for (i = 0; i < NUM_IWAD_TYPES; ++i) + { + if ([filename caseInsensitiveCompare: IWADFilenames[i]] == 0) + { + // Configure this IWAD. + + [iwadList[i] setLocation: path]; + + // Rebuild dropdown list and select the new IWAD. + + [self setDropdownList]; + [self->iwadSelector selectItemWithTitle:IWADLabels[i]]; + return YES; + } + } + + // No IWAD found with this name. + + return NO; +} + @end diff --git a/pkg/osx/LauncherManager.h b/pkg/osx/LauncherManager.h index 7e8c35cd..1c8a5187 100644 --- a/pkg/osx/LauncherManager.h +++ b/pkg/osx/LauncherManager.h @@ -41,10 +41,17 @@ - (void) runSetup: (id)sender; - (void) awakeFromNib; - (void) clearCommandLine; +- (BOOL) addIWADPath: (NSString *) path; - (void) addFileToCommandLine: (NSString *) fileName forArgument: (NSString *) args; - (void) openTerminal: (id) sender; +- (void) openREADME: (id) sender; +- (void) openINSTALL: (id) sender; +- (void) openCMDLINE: (id) sender; +- (void) openCOPYING: (id) sender; +- (void) openDocumentation: (id) sender; + @end #endif /* #ifndef LAUNCHER_LAUNCHERMANAGER_H */ diff --git a/pkg/osx/LauncherManager.m b/pkg/osx/LauncherManager.m index 36723db5..a40ac7c9 100644 --- a/pkg/osx/LauncherManager.m +++ b/pkg/osx/LauncherManager.m @@ -343,6 +343,31 @@ static NSString *AppendQuotedFilename(NSString *str, NSString *fileName) free(doomwadpath); } +- (void) openREADME: (id) sender +{ + OpenDocumentation("README"); +} + +- (void) openINSTALL: (id) sender +{ + OpenDocumentation("INSTALL"); +} + +- (void) openCMDLINE: (id) sender +{ + OpenDocumentation("CMDLINE"); +} + +- (void) openCOPYING: (id) sender +{ + OpenDocumentation("COPYING"); +} + +- (void) openDocumentation: (id) sender +{ + OpenDocumentation(""); +} + - (void) awakeFromNib { [self->launcherWindow setTitle: @PACKAGE_NAME " Launcher"]; @@ -351,5 +376,10 @@ static NSString *AppendQuotedFilename(NSString *str, NSString *fileName) [self setConfig]; } +- (BOOL) addIWADPath: (NSString *) path +{ + return [self->iwadController addIWADPath: path]; +} + @end diff --git a/pkg/osx/Resources/launcher.nib/designable.nib b/pkg/osx/Resources/launcher.nib/designable.nib index 856ea06f..b3e76d22 100644 --- a/pkg/osx/Resources/launcher.nib/designable.nib +++ b/pkg/osx/Resources/launcher.nib/designable.nib @@ -2,19 +2,19 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> <data> <int key="IBDocument.SystemTarget">1060</int> - <string key="IBDocument.SystemVersion">10F569</string> - <string key="IBDocument.InterfaceBuilderVersion">823</string> - <string key="IBDocument.AppKitVersion">1038.29</string> + <string key="IBDocument.SystemVersion">10J869</string> + <string key="IBDocument.InterfaceBuilderVersion">851</string> + <string key="IBDocument.AppKitVersion">1038.35</string> <string key="IBDocument.HIToolboxVersion">461.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> - <string key="NS.object.0">823</string> + <string key="NS.object.0">851</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="29"/> + <integer value="370"/> <integer value="2"/> - <integer value="227"/> + <integer value="228"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -600,6 +600,73 @@ <string key="NSName">_NSWindowsMenu</string> </object> </object> + <object class="NSMenuItem" id="391919375"> + <reference key="NSMenu" ref="624798014"/> + <string key="NSTitle">Help</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="733442466"> + <string key="NSTitle">Help</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="860531190"> + <reference key="NSMenu" ref="733442466"/> + <string key="NSTitle">Introduction</string> + <string key="NSKeyEquiv">?</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + <object class="NSMenuItem" id="378926680"> + <reference key="NSMenu" ref="733442466"/> + <string key="NSTitle">Set up guide</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + <object class="NSMenuItem" id="784926086"> + <reference key="NSMenu" ref="733442466"/> + <string key="NSTitle">Command line reference</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + <object class="NSMenuItem" id="913959081"> + <reference key="NSMenu" ref="733442466"/> + <string key="NSTitle">More documentation...</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + <object class="NSMenuItem" id="258703436"> + <reference key="NSMenu" ref="733442466"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + <object class="NSMenuItem" id="590365178"> + <reference key="NSMenu" ref="733442466"/> + <string key="NSTitle">Software license</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="819247708"/> + <reference key="NSMixedImage" ref="94574589"/> + </object> + </object> + <string key="NSName">_NSHelpMenu</string> + </object> + </object> </object> <string key="NSName">_NSMainMenu</string> </object> @@ -921,6 +988,26 @@ <int key="NSPeriodicInterval">25</int> </object> </object> + <object class="NSButton" id="811205099"> + <reference key="NSNextResponder" ref="145141922"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 16}, {25, 25}}</string> + <reference key="NSSuperview" ref="145141922"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="33467307"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="407649812"/> + <reference key="NSControlView" ref="811205099"/> + <int key="NSButtonFlags">-2038415105</int> + <int key="NSButtonFlags2">161</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> </object> <string key="NSFrameSize">{480, 316}</string> <reference key="NSSuperview"/> @@ -1312,6 +1399,54 @@ </object> <int key="connectionID">322</int> </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openINSTALL:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="378926680"/> + </object> + <int key="connectionID">374</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openCMDLINE:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="784926086"/> + </object> + <int key="connectionID">376</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openDocumentation:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="913959081"/> + </object> + <int key="connectionID">378</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openCOPYING:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="590365178"/> + </object> + <int key="connectionID">381</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openREADME:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="860531190"/> + </object> + <int key="connectionID">382</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openINSTALL:</string> + <reference key="source" ref="590266459"/> + <reference key="destination" ref="811205099"/> + </object> + <int key="connectionID">385</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -1442,6 +1577,7 @@ <reference ref="419477060"/> <reference ref="231654028"/> <reference ref="729612487"/> + <reference ref="391919375"/> </object> <reference key="parent" ref="0"/> <string key="objectName">MainMenu</string> @@ -1693,6 +1829,7 @@ <reference ref="625273251"/> <reference ref="680095551"/> <reference ref="658359713"/> + <reference ref="811205099"/> </object> <reference key="parent" ref="193084417"/> </object> @@ -2035,6 +2172,73 @@ <reference key="object" ref="366010945"/> <reference key="parent" ref="0"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">369</int> + <reference key="object" ref="391919375"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="733442466"/> + </object> + <reference key="parent" ref="624798014"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">370</int> + <reference key="object" ref="733442466"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="860531190"/> + <reference ref="378926680"/> + <reference ref="784926086"/> + <reference ref="913959081"/> + <reference ref="258703436"/> + <reference ref="590365178"/> + </object> + <reference key="parent" ref="391919375"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">371</int> + <reference key="object" ref="860531190"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">373</int> + <reference key="object" ref="378926680"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">375</int> + <reference key="object" ref="784926086"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">377</int> + <reference key="object" ref="913959081"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">379</int> + <reference key="object" ref="258703436"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">380</int> + <reference key="object" ref="590365178"/> + <reference key="parent" ref="733442466"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">383</int> + <reference key="object" ref="811205099"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="33467307"/> + </object> + <reference key="parent" ref="145141922"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">384</int> + <reference key="object" ref="33467307"/> + <reference key="parent" ref="811205099"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -2043,6 +2247,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>129.IBPluginDependency</string> <string>129.ImportedFromIB2</string> + <string>130.IBEditorWindowLastContentRect</string> <string>130.IBPluginDependency</string> <string>130.ImportedFromIB2</string> <string>131.IBPluginDependency</string> @@ -2131,6 +2336,7 @@ <string>238.ImportedFromIB2</string> <string>239.IBPluginDependency</string> <string>239.ImportedFromIB2</string> + <string>24.IBEditorWindowLastContentRect</string> <string>24.IBPluginDependency</string> <string>24.ImportedFromIB2</string> <string>240.IBPluginDependency</string> @@ -2158,6 +2364,7 @@ <string>270.ImportedFromIB2</string> <string>274.IBPluginDependency</string> <string>274.ImportedFromIB2</string> + <string>275.IBEditorWindowLastContentRect</string> <string>275.IBPluginDependency</string> <string>275.ImportedFromIB2</string> <string>281.IBPluginDependency</string> @@ -2184,10 +2391,22 @@ <string>349.IBPluginDependency</string> <string>350.IBPluginDependency</string> <string>351.IBPluginDependency</string> + <string>369.IBPluginDependency</string> + <string>370.IBEditorWindowLastContentRect</string> + <string>370.IBPluginDependency</string> + <string>371.IBPluginDependency</string> + <string>373.IBPluginDependency</string> + <string>375.IBPluginDependency</string> + <string>377.IBPluginDependency</string> + <string>379.IBPluginDependency</string> + <string>380.IBPluginDependency</string> + <string>383.IBPluginDependency</string> + <string>384.IBPluginDependency</string> <string>5.IBPluginDependency</string> <string>5.ImportedFromIB2</string> <string>56.IBPluginDependency</string> <string>56.ImportedFromIB2</string> + <string>57.IBEditorWindowLastContentRect</string> <string>57.IBPluginDependency</string> <string>57.ImportedFromIB2</string> <string>58.IBPluginDependency</string> @@ -2199,6 +2418,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> + <string>{{576, 728}, {64, 6}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2231,9 +2451,9 @@ <bytes key="NSTransformStruct">P4AAAL+AAABBiAAAwyEAAA</bytes> </object> <boolean value="YES"/> - <string>{{337, 406}, {530, 190}}</string> + <string>{{368, 418}, {530, 190}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{337, 406}, {530, 190}}</string> + <string>{{368, 418}, {530, 190}}</string> <boolean value="YES"/> <boolean value="YES"/> <boolean value="YES"/> @@ -2274,13 +2494,13 @@ <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <object class="NSAffineTransform"> - <bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwgQAAA</bytes> + <bytes key="NSTransformStruct">P4AAAL+AAABBYAAAwigAAA</bytes> </object> <boolean value="YES"/> <boolean value="YES"/> - <string>{{329, 484}, {480, 316}}</string> + <string>{{421, 438}, {480, 316}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{329, 484}, {480, 316}}</string> + <string>{{421, 438}, {480, 316}}</string> <boolean value="YES"/> <boolean value="YES"/> <string>{213, 107}</string> @@ -2303,6 +2523,7 @@ <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> + <string>{{469, 741}, {194, 73}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2330,6 +2551,7 @@ <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> + <string>{{425, 661}, {151, 153}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2340,7 +2562,7 @@ <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> - <string>{{329, 814}, {223, 20}}</string> + <string>{{329, 814}, {272, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2357,9 +2579,21 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{540, 701}, {238, 113}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> + <string>{{341, 611}, {235, 203}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="YES"/> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2384,7 +2618,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">351</int> + <int key="maxID">385</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -2410,6 +2644,7 @@ </object> <object class="IBPartialClassDescription"> <string key="className">FirstResponder</string> + <string key="superclassName">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBUserSource</string> <string key="minorKey"/> @@ -2560,6 +2795,11 @@ <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>launch:</string> + <string>openCMDLINE:</string> + <string>openCOPYING:</string> + <string>openDocumentation:</string> + <string>openINSTALL:</string> + <string>openREADME:</string> <string>openTerminal:</string> <string>runSetup:</string> </object> @@ -2568,6 +2808,11 @@ <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="actionInfosByName"> @@ -2575,6 +2820,11 @@ <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>launch:</string> + <string>openCMDLINE:</string> + <string>openCOPYING:</string> + <string>openDocumentation:</string> + <string>openINSTALL:</string> + <string>openREADME:</string> <string>openTerminal:</string> <string>runSetup:</string> </object> @@ -2585,6 +2835,26 @@ <string key="candidateClassName">id</string> </object> <object class="IBActionInfo"> + <string key="name">openCMDLINE:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">openCOPYING:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">openDocumentation:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">openINSTALL:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> + <string key="name">openREADME:</string> + <string key="candidateClassName">id</string> + </object> + <object class="IBActionInfo"> <string key="name">openTerminal:</string> <string key="candidateClassName">id</string> </object> diff --git a/pkg/osx/Resources/launcher.nib/keyedobjects.nib b/pkg/osx/Resources/launcher.nib/keyedobjects.nib Binary files differindex 93066265..7df7670c 100644 --- a/pkg/osx/Resources/launcher.nib/keyedobjects.nib +++ b/pkg/osx/Resources/launcher.nib/keyedobjects.nib diff --git a/pkg/osx/disk/background.png b/pkg/osx/disk/background.png Binary files differnew file mode 100644 index 00000000..07c3d81b --- /dev/null +++ b/pkg/osx/disk/background.png diff --git a/pkg/osx/disk/dir.DS_Store b/pkg/osx/disk/dir.DS_Store Binary files differnew file mode 100644 index 00000000..b7104637 --- /dev/null +++ b/pkg/osx/disk/dir.DS_Store diff --git a/pkg/osx/dmgfix b/pkg/osx/dmgfix new file mode 100755 index 00000000..560b17ed --- /dev/null +++ b/pkg/osx/dmgfix @@ -0,0 +1,64 @@ +#!/usr/bin/osascript +-- +-- Copyright(C) 2009 Simon Howard +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. +-- +-- +-- AppleScript script to automatically set the view properties in a +-- .dmg file - ie. the background image, other Finder view options +-- and icon positions. +-- +-- Usage: dmgfix <absolute path to dmg> <disk name> <name of app> +-- + +on run argv + set dmgFile to POSIX file (item 1 of argv) + set diskName to item 2 of argv + set appName to item 3 of argv + + tell application "Finder" + --activate + open dmgFile + delay 1 + set win to the front Finder window + set theDisk to disk diskName + set the target of win to theDisk + + -- window options: + + set bgfile to file "background.png" of theDisk + set the bounds of win to {200, 200, 717, 536} + set icon size of icon view options of win to 96 + set background picture of icon view options of win to bgfile + set toolbar visible of win to false + + -- hide background file: + + set bgloc to quoted form of POSIX path of (bgfile as text) + do shell script "SetFile -a V " & bgloc + + -- icon positions: + + set position of file "README" of theDisk to {120, 250} + set position of file "Software License" of theDisk to {380, 250} + set position of file appName of theDisk to {70, 110} + set position of file "Applications" of theDisk to {450, 110} + + eject theDisk + end tell +end run + diff --git a/pkg/win32/GNUmakefile b/pkg/win32/GNUmakefile index bfe4f7ef..6b45152e 100644 --- a/pkg/win32/GNUmakefile +++ b/pkg/win32/GNUmakefile @@ -29,6 +29,10 @@ staging: $(EXE_FILES) $(DLL_FILES) $(patsubst %,../../%,$(DOC_FILES)) cp $(TOPLEVEL)/$$f staging/$$f.txt; \ unix2dos staging/$$f.txt; \ done + $(TOPLEVEL)/man/simplecpp -D_WIN32 -DPRECOMPILED \ + < $(TOPLEVEL)/man/INSTALL.template \ + > staging/INSTALL.txt + unix2dos staging/INSTALL.txt clean: rm -f $(ZIP) diff --git a/rpm.spec.in b/rpm.spec.in index 9717ebfb..137a9517 100644 --- a/rpm.spec.in +++ b/rpm.spec.in @@ -49,14 +49,8 @@ rm -rf $RPM_BUILD_ROOT %files %doc %{_mandir}/man5/* %doc %{_mandir}/man6/* -%doc README -%doc README.OPL -%doc INSTALL -%doc NEWS -%doc AUTHORS -%doc COPYING -%doc CMDLINE -%doc BUGS -%doc NOT-BUGS +/usr/share/doc/@PACKAGE@/* /usr/games/* +/usr/share/icons/* +/usr/share/applications/* diff --git a/src/Makefile.am b/src/Makefile.am index 5dc9fe11..746a015b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -191,6 +191,18 @@ EXTRA_DIST = \ icon.c \ doom-screensaver.desktop.in +appdir = $(prefix)/share/applications +app_DATA = @PROGRAM_PREFIX@doom.desktop + +@PROGRAM_PREFIX@doom.desktop : doom.desktop + cp $^ $@ + +screensaverdir = $(prefix)/share/applications/screensavers +screensaver_DATA = @PROGRAM_PREFIX@doom-screensaver.desktop + +@PROGRAM_PREFIX@doom-screensaver.desktop: doom-screensaver.desktop + cp $^ $@ + .rc.o: $(WINDRES) $^ -o $@ %.o : %.rc diff --git a/src/d_mode.h b/src/d_mode.h index 29f61c10..1c4fff64 100644 --- a/src/d_mode.h +++ b/src/d_mode.h @@ -65,6 +65,7 @@ typedef enum exe_hacx, // Hacx exe_ultimate, // Ultimate Doom (retail) exe_final, // Final Doom + exe_final2, // Final Doom (alternate exe) exe_chex, // Chex Quest executable (based on Final Doom) exe_heretic_1_3, // Heretic 1.3 diff --git a/src/deh_io.c b/src/deh_io.c index 92c81632..83609068 100644 --- a/src/deh_io.c +++ b/src/deh_io.c @@ -181,7 +181,7 @@ int DEH_GetCharLump(deh_context_t *context) int DEH_GetChar(deh_context_t *context) { - int result; + int result = 0; // Read characters, but ignore carriage returns // Essentially this is a DOS->Unix conversion diff --git a/src/doom-screensaver.desktop.in b/src/doom-screensaver.desktop.in index cee79c2d..178575a2 100644 --- a/src/doom-screensaver.desktop.in +++ b/src/doom-screensaver.desktop.in @@ -1,10 +1,10 @@ [Desktop Entry] Encoding=UTF-8 -Name=Doom -Comment=DOOM by Id Software. -TryExec=@PACKAGE_TARNAME@ -Exec=@PACKAGE_TARNAME@ +Name=@PACKAGE_NAME@ +Comment=@PACKAGE_SHORTDESC@ +TryExec=@PROGRAM_PREFIX@doom +Exec=@PROGRAM_PREFIX@doom StartupNotify=false Terminal=false Type=Application diff --git a/src/doom.desktop.in b/src/doom.desktop.in new file mode 100644 index 00000000..44b76e62 --- /dev/null +++ b/src/doom.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=@PACKAGE_NAME@ +Exec=@PROGRAM_PREFIX@doom +Icon=@PROGRAM_PREFIX@doom +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; diff --git a/src/doom/d_main.c b/src/doom/d_main.c index 991907fa..f626d408 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -532,6 +532,9 @@ void D_DoAdvanceDemo (void) // include a DEMO4 lump, so the game bombs out with an error // when it reaches this point in the demo sequence. + // However! There is an alternate version of Final Doom that + // includes a fixed executable. + if (gameversion == exe_ultimate || gameversion == exe_final) demosequence = (demosequence+1)%7; else @@ -914,6 +917,7 @@ static struct {"Hacx", "hacx", exe_hacx}, {"Ultimate Doom", "ultimate", exe_ultimate}, {"Final Doom", "final", exe_final}, + {"Final Doom (alt)", "final2", exe_final2}, {"Chex Quest", "chex", exe_chex}, { NULL, NULL, 0}, }; @@ -930,7 +934,7 @@ static void InitGameVersion(void) // @category compat // // Emulate a specific version of Doom. Valid values are "1.9", - // "ultimate" and "final". + // "ultimate", "final", "final2", "hacx" and "chex". // p = M_CheckParmWithArgs("-gameversion", 1); @@ -994,8 +998,10 @@ static void InitGameVersion(void) else { // Final Doom: tnt or plutonia + // Default to the "alt" version of the executable that + // fixes the demo loop behavior. - gameversion = exe_final; + gameversion = exe_final2; } } } @@ -1034,11 +1040,37 @@ void PrintGameVersion(void) static void LoadChexDeh(void) { - char *chex_deh; + char *chex_deh = NULL; + char *sep; if (gameversion == exe_chex) { - chex_deh = D_FindWADByName("chex.deh"); + // Look for chex.deh in the same directory as the IWAD file. + + sep = strrchr(iwadfile, DIR_SEPARATOR); + + if (sep != NULL) + { + chex_deh = malloc(strlen(iwadfile) + 9); + strcpy(chex_deh, iwadfile); + chex_deh[sep - iwadfile + 1] = '\0'; + strcat(chex_deh, "chex.deh"); + } + else + { + chex_deh = strdup("chex.deh"); + } + + // If the dehacked patch isn't found, try searching the WAD + // search path instead. We might find it... + + if (!M_FileExists(chex_deh)) + { + free(chex_deh); + chex_deh = D_FindWADByName("chex.deh"); + } + + // Still not found? if (chex_deh == NULL) { diff --git a/src/doom/d_net.c b/src/doom/d_net.c index dd1ec563..f3155a9b 100644 --- a/src/doom/d_net.c +++ b/src/doom/d_net.c @@ -474,7 +474,8 @@ boolean D_InitNetGame(net_connect_data_t *connect_data, // Start a multiplayer server, listening for connections. // - if (M_CheckParm("-server") > 0) + if (M_CheckParm("-server") > 0 + || M_CheckParm("-privateserver") > 0) { NET_SV_Init(); NET_SV_AddModule(&net_loop_server_module); diff --git a/src/doom/doom.desktop.in b/src/doom/doom.desktop.in new file mode 100644 index 00000000..44b76e62 --- /dev/null +++ b/src/doom/doom.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=@PACKAGE_NAME@ +Exec=@PROGRAM_PREFIX@doom +Icon=@PROGRAM_PREFIX@doom +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; diff --git a/src/doom/doomstat.c b/src/doom/doomstat.c index b591358f..2bbb45e7 100644 --- a/src/doom/doomstat.c +++ b/src/doom/doomstat.c @@ -32,7 +32,7 @@ // Game Mode - identify IWAD as shareware, retail etc. GameMode_t gamemode = indetermined; GameMission_t gamemission = doom; -GameVersion_t gameversion = exe_final; +GameVersion_t gameversion = exe_final2; char *gamedescription; // Set if homebrew PWAD stuff has been added. diff --git a/src/doom/g_game.c b/src/doom/g_game.c index 5662d3f2..598f1c5e 100644 --- a/src/doom/g_game.c +++ b/src/doom/g_game.c @@ -361,6 +361,13 @@ int G_CmdChecksum (ticcmd_t* cmd) static boolean WeaponSelectable(weapontype_t weapon) { + // Can't select the super shotgun in Doom 1. + + if (weapon == wp_supershotgun && gamemission == doom) + { + return false; + } + // Can't select a weapon if we don't own it. if (!players[consoleplayer].weaponowned[weapon]) diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c index 478e7f66..4a365cfb 100644 --- a/src/doom/m_menu.c +++ b/src/doom/m_menu.c @@ -798,6 +798,7 @@ void M_DrawReadThis1(void) break; case exe_final: + case exe_final2: // Final Doom always displays "HELP". diff --git a/src/doom/p_map.c b/src/doom/p_map.c index 78102bdf..7e92e23a 100644 --- a/src/doom/p_map.c +++ b/src/doom/p_map.c @@ -885,24 +885,16 @@ PTR_AimTraverse (intercept_t* in) dist = FixedMul (attackrange, in->frac); - // Return false if there is no back sector. This should never - // be the case if the line is two-sided; however, some WADs - // (eg. ottawau.wad) use this as an "impassible glass" trick - // and rely on Vanilla Doom's (unintentional) support for this. - - if (li->backsector == NULL) - { - return false; - } - - if (li->frontsector->floorheight != li->backsector->floorheight) + if (li->backsector == NULL + || li->frontsector->floorheight != li->backsector->floorheight) { slope = FixedDiv (openbottom - shootz , dist); if (slope > bottomslope) bottomslope = slope; } - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + if (li->backsector == NULL + || li->frontsector->ceilingheight != li->backsector->ceilingheight) { slope = FixedDiv (opentop - shootz , dist); if (slope < topslope) @@ -983,26 +975,35 @@ boolean PTR_ShootTraverse (intercept_t* in) dist = FixedMul (attackrange, in->frac); - // Check if backsector is NULL. See comment in PTR_AimTraverse. + // e6y: emulation of missed back side on two-sided lines. + // backsector can be NULL when emulating missing back side. - if (li->backsector == NULL) + if (li->backsector == NULL) { - goto hitline; - } + slope = FixedDiv (openbottom - shootz , dist); + if (slope > aimslope) + goto hitline; - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > aimslope) - goto hitline; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv (opentop - shootz , dist); - if (slope < aimslope) - goto hitline; - } + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + else + { + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > aimslope) + goto hitline; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + } // shot continues return true; diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c index 3fc95cab..58d5f462 100644 --- a/src/doom/p_setup.c +++ b/src/doom/p_setup.c @@ -155,7 +155,24 @@ void P_LoadVertexes (int lump) W_ReleaseLumpNum(lump); } +// +// GetSectorAtNullAddress +// +sector_t* GetSectorAtNullAddress(void) +{ + static boolean null_sector_is_initialized = false; + static sector_t null_sector; + + if (!null_sector_is_initialized) + { + memset(&null_sector, 0, sizeof(null_sector)); + I_GetMemoryValue(0, &null_sector.floorheight, 4); + I_GetMemoryValue(4, &null_sector.ceilingheight, 4); + null_sector_is_initialized = true; + } + return &null_sector; +} // // P_LoadSegs @@ -204,10 +221,12 @@ void P_LoadSegs (int lump) if (sidenum < 0 || sidenum >= numsides) { - sidenum = 0; + li->backsector = GetSectorAtNullAddress(); + } + else + { + li->backsector = sides[sidenum].sector; } - - li->backsector = sides[sidenum].sector; } else { @@ -681,7 +700,7 @@ static void PadRejectArray(byte *array, unsigned int len) if (len > sizeof(rejectpad)) { fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%i > %i)\n", - len, sizeof(rejectpad)); + len, (int) sizeof(rejectpad)); // Pad remaining space with 0 (or 0xff, if specified on command line). diff --git a/src/doom/st_stuff.c b/src/doom/st_stuff.c index 7e5e225c..8595ff50 100644 --- a/src/doom/st_stuff.c +++ b/src/doom/st_stuff.c @@ -525,8 +525,13 @@ ST_Responder (event_t* ev) plyr->message = DEH_String(STSTR_MUS); cht_GetParam(&cheat_mus, buf); - - if (gamemode == commercial) + + // Note: The original v1.9 had a bug that tried to play back + // the Doom II music regardless of gamemode. This was fixed + // in the Ultimate Doom executable so that it would work for + // the Doom 1 music as well. + + if (gamemode == commercial || gameversion < exe_ultimate) { musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1; diff --git a/src/i_endoom.c b/src/i_endoom.c index 021a3604..09c2d2d2 100644 --- a/src/i_endoom.c +++ b/src/i_endoom.c @@ -67,7 +67,7 @@ void I_Endoom(byte *endoom_data) { TXT_UpdateScreen(); - if (TXT_GetChar() >= 0) + if (TXT_GetChar() > 0) { break; } diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index e7a42e83..dd35ce5e 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -1079,7 +1079,7 @@ static void ScheduleTrack(opl_track_data_t *track); // Restart a song from the beginning. -static void RestartSong(void) +static void RestartSong(void *unused) { unsigned int i; @@ -1117,10 +1117,15 @@ static void TrackTimerCallback(void *arg) --running_tracks; // When all tracks have finished, restart the song. + // Don't restart the song immediately, but wait for 5ms + // before triggering a restart. Otherwise it is possible + // to construct an empty MIDI file that causes the game + // to lock up in an infinite loop. (5ms should be short + // enough not to be noticeable by the listener). if (running_tracks <= 0 && song_looping) { - RestartSong(); + OPL_SetCallback(5, RestartSong, NULL); } return; diff --git a/src/i_scale.c b/src/i_scale.c index 2c0b718c..6d03d708 100644 --- a/src/i_scale.c +++ b/src/i_scale.c @@ -33,6 +33,7 @@ #include "doomtype.h" #include "i_video.h" +#include "m_argv.h" #include "z_zone.h" #if defined(_MSC_VER) && !defined(__cplusplus) @@ -967,6 +968,21 @@ static boolean I_Stretch5x(int x1, int y1, int x2, int y2) screenp += dest_pitch; bufp += SCREENWIDTH; } + // test hack for Porsche Monty... scan line simulation: + // See here: http://www.doomworld.com/vb/post/962612 + + if (M_CheckParm("-scanline") > 0) + { + screenp = (byte *) dest_buffer + 2 * dest_pitch; + + for (y=0; y<1198; y += 3) + { + memset(screenp, 0, 1600); + + screenp += dest_pitch * 3; + } + } + return true; } diff --git a/src/i_system.c b/src/i_system.c index 0a856ca9..1d961956 100644 --- a/src/i_system.c +++ b/src/i_system.c @@ -55,6 +55,10 @@ #include "w_wad.h" #include "z_zone.h" +#ifdef __MACOSX__ +#include <CoreFoundation/CFUserNotification.h> +#endif + #define DEFAULT_RAM 16 /* MiB */ #define MIN_RAM 4 /* MiB */ @@ -282,7 +286,6 @@ void I_BindVariables(void) } */ - // // I_Quit // @@ -366,8 +369,151 @@ void I_Error (char *error, ...) } #endif +#ifdef __MACOSX__ + { + CFStringRef message; + char msgbuf[512]; + int i; + + va_start(argptr, error); + memset(msgbuf, 0, sizeof(msgbuf)); + vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr); + va_end(argptr); + + // The CoreFoundation message box wraps text lines, so replace + // newline characters with spaces so that multiline messages + // are continuous. + + for (i = 0; msgbuf[i] != '\0'; ++i) + { + if (msgbuf[i] == '\n') + { + msgbuf[i] = ' '; + } + } + + message = CFStringCreateWithCString(NULL, msgbuf, + kCFStringEncodingUTF8); + + CFUserNotificationDisplayNotice(0, + kCFUserNotificationCautionAlertLevel, + NULL, + NULL, + NULL, + CFSTR(PACKAGE_STRING), + message, + NULL); + } +#endif + // abort(); exit(-1); } +// +// Read Access Violation emulation. +// +// From PrBoom+, by entryway. +// + +// C:\>debug +// -d 0:0 +// +// DOS 6.22: +// 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) +// DOS 7.1: +// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) +// Win98: +// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) +// DOSBox under XP: +// 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + +#define DOS_MEM_DUMP_SIZE 10 + +static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = { + 0x57, 0x92, 0x19, 0x00, 0xF4, 0x06, 0x70, 0x00, 0x16, 0x00}; +static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = { + 0x9E, 0x0F, 0xC9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00}; +static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = { + 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00}; +static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE]; + +static const unsigned char *dos_mem_dump = mem_dump_dos622; + +boolean I_GetMemoryValue(unsigned int offset, void *value, int size) +{ + static boolean firsttime = true; + + if (firsttime) + { + int p, i, val; + + firsttime = false; + i = 0; + + //! + // @category compat + // @arg <version> + // + // Specify DOS version to emulate for NULL pointer dereference + // emulation. Supported versions are: dos622, dos71, dosbox. + // The default is to emulate DOS 7.1 (Windows 98). + // + + p = M_CheckParmWithArgs("-setmem", 1); + + if (p > 0) + { + if (!strcasecmp(myargv[p + 1], "dos622")) + { + dos_mem_dump = mem_dump_dos622; + } + if (!strcasecmp(myargv[p + 1], "dos71")) + { + dos_mem_dump = mem_dump_win98; + } + else if (!strcasecmp(myargv[p + 1], "dosbox")) + { + dos_mem_dump = mem_dump_dosbox; + } + else + { + for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i) + { + ++p; + + if (p >= myargc || myargv[p][0] == '-') + { + break; + } + + M_StrToInt(myargv[p], &val); + mem_dump_custom[i++] = (unsigned char) val; + } + + dos_mem_dump = mem_dump_custom; + } + } + } + + switch (size) + { + case 1: + *((unsigned char *) value) = dos_mem_dump[offset]; + return true; + case 2: + *((unsigned short *) value) = dos_mem_dump[offset] + | (dos_mem_dump[offset + 1] << 8); + return true; + case 4: + *((unsigned int *) value) = dos_mem_dump[offset] + | (dos_mem_dump[offset + 1] << 8) + | (dos_mem_dump[offset + 2] << 16) + | (dos_mem_dump[offset + 3] << 24); + return true; + } + + return false; +} + diff --git a/src/i_system.h b/src/i_system.h index 0697f7db..5a99b213 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -71,6 +71,8 @@ void I_Tactile (int on, int off, int total); void I_Error (char *error, ...); +boolean I_GetMemoryValue(unsigned int offset, void *value, int size); + // Schedule a function to be called when the program exits. // If run_if_error is true, the function is called if the exit // is due to an error (I_Error) diff --git a/src/i_video.c b/src/i_video.c index 9d70e88e..6a3175bb 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -656,7 +656,7 @@ static int GetTypedChar(SDL_Event *event) { // Unicode value, from key layout. - return event->key.keysym.unicode; + return tolower(event->key.keysym.unicode); } } diff --git a/src/m_misc.c b/src/m_misc.c index ed41b5f1..e14436a3 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -209,8 +209,9 @@ boolean M_StrToInt(const char *str, int *result) void M_ExtractFileBase(char *path, char *dest) { - char* src; - int length; + char *src; + char *filename; + int length; src = path + strlen(path) - 1; @@ -220,20 +221,26 @@ void M_ExtractFileBase(char *path, char *dest) src--; } - // copy up to eight characters - memset(dest, 0, 8); + filename = src; + + // Copy up to eight characters + // Note: Vanilla Doom exits with an error if a filename is specified + // with a base of more than eight characters. To remove the 8.3 + // filename limit, instead we simply truncate the name. + length = 0; + memset(dest, 0, 8); while (*src != '\0' && *src != '.') { - ++length; - - if (length > 8) + if (length >= 8) { - I_Error ("Filename base of %s >8 chars", path); + printf("Warning: Truncated '%s' lump name to '%.8s'.\n", + filename, dest); + break; } - *dest++ = toupper((int)*src++); + dest[length++] = toupper((int)*src++); } } diff --git a/src/net_server.c b/src/net_server.c index ae46be4a..157f5069 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1563,6 +1563,7 @@ void NET_SV_RegisterWithMaster(void) { //! // When running a server, don't register with the global master server. + // Implies -server. // // @category net // diff --git a/src/setup/Makefile.am b/src/setup/Makefile.am index 25ab38e3..7fe051ee 100644 --- a/src/setup/Makefile.am +++ b/src/setup/Makefile.am @@ -27,6 +27,12 @@ libsetup_a_SOURCES = $(SOURCE_FILES) EXTRA_DIST= \ setup_icon.c +appdir = $(prefix)/share/applications +app_DATA = @PROGRAM_PREFIX@setup.desktop + +@PROGRAM_PREFIX@setup.desktop : setup.desktop + cp $^ $@ + if HAVE_PYTHON setup_icon.c : $(top_builddir)/data/setup8.ico diff --git a/src/setup/display.c b/src/setup/display.c index 9ed0ae5f..72f3c057 100644 --- a/src/setup/display.c +++ b/src/setup/display.c @@ -527,25 +527,34 @@ static void UpdateBPP(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(modes_table)) GenerateModesTable(NULL, modes_table); } -#if defined(_WIN32) && !defined(_WIN32_WCE) +static void UpdateModeSeparator(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(separator)) +{ + TXT_CAST_ARG(txt_separator_t, separator); + + if (fullscreen) + { + TXT_SetSeparatorLabel(separator, "Screen mode"); + } + else + { + TXT_SetSeparatorLabel(separator, "Window size"); + } +} -static int win32_video_driver = 0; +#if defined(_WIN32) && !defined(_WIN32_WCE) -static char *win32_video_drivers[] = -{ - "DirectX", - "Windows GDI", -}; +static int use_directx = 1; static void SetWin32VideoDriver(void) { if (!strcmp(video_driver, "windib")) { - win32_video_driver = 1; + use_directx = 0; } else { - win32_video_driver = 0; + use_directx = 1; } } @@ -553,13 +562,15 @@ static void UpdateVideoDriver(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(modes_table)) { TXT_CAST_ARG(txt_table_t, modes_table); - char *drivers[] = - { - "", - "windib", - }; - video_driver = drivers[win32_video_driver != 0]; + if (use_directx) + { + video_driver = ""; + } + else + { + video_driver = "windib"; + } // When the video driver is changed, we need to restart the textscreen // library. @@ -579,16 +590,72 @@ static void UpdateVideoDriver(TXT_UNCAST_ARG(widget), #endif +static void AdvancedDisplayConfig(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(modes_table)) +{ + TXT_CAST_ARG(txt_table_t, modes_table); + txt_window_t *window; + txt_checkbox_t *ar_checkbox; + + window = TXT_NewWindow("Advanced display options"); + + TXT_SetColumnWidths(window, 35); + + TXT_AddWidgets(window, + ar_checkbox = TXT_NewCheckBox("Fix aspect ratio", + &aspect_ratio_correct), + NULL); + + if (gamemission == heretic || gamemission == hexen) + { + TXT_AddWidget(window, + TXT_NewCheckBox("Graphical startup", &graphical_startup)); + } + + if (gamemission == doom || gamemission == heretic) + { + TXT_AddWidget(window, + TXT_NewCheckBox("Show ENDOOM screen on exit", + &show_endoom)); + } + + TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table); + + // On Windows, there is an extra control to change between + // the Windows GDI and DirectX video drivers. + +#if defined(_WIN32) && !defined(_WIN32_WCE) + { + txt_radiobutton_t *dx_button, *gdi_button; + + TXT_AddWidgets(window, + TXT_NewSeparator("Windows video driver"), + dx_button = TXT_NewRadioButton("DirectX", + &use_directx, 1), + gdi_button = TXT_NewRadioButton("Windows GDI", + &use_directx, 0), + NULL); + + TXT_SignalConnect(dx_button, "selected", + UpdateVideoDriver, modes_table); + TXT_SignalConnect(gdi_button, "selected", + UpdateVideoDriver, modes_table); + SetWin32VideoDriver(); + } +#endif +} void ConfigDisplay(void) { txt_window_t *window; txt_table_t *modes_table; + txt_separator_t *modes_separator; txt_table_t *bpp_table; + txt_window_action_t *advanced_button; txt_checkbox_t *fs_checkbox; - txt_checkbox_t *ar_checkbox; - txt_dropdown_list_t *bpp_selector; + int i; int num_columns; + int num_rows; int window_y; // What color depths are supported? Generate supported_bpps array @@ -606,14 +673,8 @@ void ConfigDisplay(void) } // Open the window - - window = TXT_NewWindow("Display Configuration"); - TXT_AddWidgets(window, - fs_checkbox = TXT_NewCheckBox("Fullscreen", &fullscreen), - ar_checkbox = TXT_NewCheckBox("Correct aspect ratio", - &aspect_ratio_correct), - NULL); + window = TXT_NewWindow("Display Configuration"); // Some machines can have lots of video modes. This tries to // keep a limit of six lines by increasing the number of @@ -621,93 +682,101 @@ void ConfigDisplay(void) BuildFullscreenModesList(); - window_y = 5; - - if (num_screen_modes_fullscreen <= 18) + if (num_screen_modes_fullscreen <= 24) { num_columns = 3; } - else if (num_screen_modes_fullscreen <= 24) + else if (num_screen_modes_fullscreen <= 40) { num_columns = 4; } else { num_columns = 5; - window_y -= 3; } modes_table = TXT_NewTable(num_columns); - // The window is set at a fixed vertical position. This keeps - // the top of the window stationary when switching between - // fullscreen and windowed mode (which causes the window's - // height to change). + // Build window: - TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, - TXT_SCREEN_W / 2, window_y); + TXT_AddWidget(window, + fs_checkbox = TXT_NewCheckBox("Full screen", &fullscreen)); - // On Windows, there is an extra control to change between - // the Windows GDI and DirectX video drivers. - -#if defined(_WIN32) && !defined(_WIN32_WCE) + if (num_supported_bpps > 1) { - txt_table_t *driver_table; - txt_dropdown_list_t *driver_list; - - driver_table = TXT_NewTable(2); - - TXT_SetColumnWidths(driver_table, 20, 0); - - TXT_AddWidgets(driver_table, - TXT_NewLabel("Video driver"), - driver_list = TXT_NewDropdownList(&win32_video_driver, - win32_video_drivers, - 2), + TXT_AddWidgets(window, + TXT_NewSeparator("Color depth"), + bpp_table = TXT_NewTable(4), NULL); - TXT_SignalConnect(driver_list, "changed", - UpdateVideoDriver, modes_table); - SetWin32VideoDriver(); + for (i = 0; i < num_supported_bpps; ++i) + { + txt_radiobutton_t *button; - TXT_AddWidget(window, driver_table); - } -#endif + button = TXT_NewRadioButton(supported_bpps[i], + &selected_bpp, i); - // Screen modes list + TXT_AddWidget(bpp_table, button); + TXT_SignalConnect(button, "selected", UpdateBPP, modes_table); + } + } TXT_AddWidgets(window, - TXT_NewSeparator("Screen mode"), - bpp_table = TXT_NewTable(2), + modes_separator = TXT_NewSeparator(""), modes_table, - TXT_NewSeparator("Misc."), NULL); - if (gamemission == heretic || gamemission == hexen) + TXT_SignalConnect(fs_checkbox, "changed", + GenerateModesTable, modes_table); + TXT_SignalConnect(fs_checkbox, "changed", + UpdateModeSeparator, modes_separator); + + // How many rows high will the configuration window be? + // Need to take into account number of fullscreen modes, and also + // number of supported pixel depths. + // The windowed modes list is four rows, so take the maximum of + // windowed and fullscreen. + + num_rows = (num_screen_modes_fullscreen + num_columns - 1) / num_columns; + + if (num_rows < 4) { - TXT_AddWidget(window, - TXT_NewCheckBox("Graphical startup", &graphical_startup)); + num_rows = 4; } - if (gamemission == doom || gamemission == heretic) + if (num_supported_bpps > 1) { - TXT_AddWidget(window, - TXT_NewCheckBox("Show ENDOOM screen", &show_endoom)); + num_rows += 2; } - TXT_AddWidgets(bpp_table, - TXT_NewLabel("Color depth: "), - bpp_selector = TXT_NewDropdownList(&selected_bpp, - supported_bpps, - num_supported_bpps), - NULL); + if (num_rows < 14) + { + window_y = 8 - ((num_rows + 1) / 2); + } + else + { + window_y = 1; + } + // The window is set at a fixed vertical position. This keeps + // the top of the window stationary when switching between + // fullscreen and windowed mode (which causes the window's + // height to change). - TXT_SignalConnect(bpp_selector, "changed", UpdateBPP, modes_table); - TXT_SignalConnect(fs_checkbox, "changed", GenerateModesTable, modes_table); - TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table); + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, + TXT_SCREEN_W / 2, window_y); GenerateModesTable(NULL, modes_table); + UpdateModeSeparator(NULL, modes_separator); + + // Button to open "advanced" window. + // Need to pass a pointer to the modes table, as some of the options + // in there trigger a rebuild of it. + + advanced_button = TXT_NewWindowAction('a', "Advanced"); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, advanced_button); + TXT_SignalConnect(advanced_button, "pressed", + AdvancedDisplayConfig, modes_table); } void BindDisplayVariables(void) diff --git a/src/setup/joystick.c b/src/setup/joystick.c index 0fc00ea1..2a7b1f79 100644 --- a/src/setup/joystick.c +++ b/src/setup/joystick.c @@ -27,6 +27,7 @@ #include "m_controls.h" #include "textscreen.h" +#include "execute.h" #include "joystick.h" #include "mode.h" #include "txt_joybinput.h" @@ -436,6 +437,8 @@ void ConfigJoystick(void) TXT_SignalConnect(joystick_button, "pressed", CalibrateJoystick, NULL); TXT_SignalConnect(window, "closed", JoystickWindowClosed, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); + SetJoystickButtonLabel(); } diff --git a/src/setup/setup-manifest.xml.in b/src/setup/setup-manifest.xml.in index bac9a05e..ff879263 100644 --- a/src/setup/setup-manifest.xml.in +++ b/src/setup/setup-manifest.xml.in @@ -1,16 +1,33 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> + +<!-- Magic manifest file that should make Windows Vista/7 not + attempt to gain elevated privileges for chocolate-setup. + + Based on: + + http://www.cygwin.com/ml/cygwin/2006-12/msg00580.html + --> + <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <!-- The "name" field in this tag should be the same as the executable's name --> - <assemblyIdentity version="@PACKAGE_VERSION@.0" processorArchitecture="*" - name="@PROGRAM_PREFIX@setup" type="win32"/> + <assemblyIdentity version="0.0.0.0" processorArchitecture="X86" + name="@PROGRAM_PREFIX@setup.exe" type="win32"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> - <!-- Hi Vista! We don't require elevated privileges. Thanks! --> - <requestedExecutionLevel level="asInvoker"/> + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> + + <!-- Stop the Program Compatibility Assistant appearing: --> + + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- 7 --> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!-- Vista --> + </application> + </compatibility> </assembly> diff --git a/src/setup/setup.desktop.in b/src/setup/setup.desktop.in new file mode 100644 index 00000000..79fb38be --- /dev/null +++ b/src/setup/setup.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=@PACKAGE_NAME@ Setup +Exec=@PROGRAM_PREFIX@setup +Icon=@PROGRAM_PREFIX@setup +Type=Application +Comment=Setup tool for @PACKAGE_NAME@ +Categories=Settings;ConsoleOnly; diff --git a/src/setup/sound.c b/src/setup/sound.c index 627549b5..9e13edd9 100644 --- a/src/setup/sound.c +++ b/src/setup/sound.c @@ -68,7 +68,7 @@ static char *musicmode_strings[] = int snd_sfxdevice = SNDDEVICE_SB; int snd_musicdevice = SNDDEVICE_GENMIDI; -int snd_samplerate = 22050; +int snd_samplerate = 44100; int opl_io_port = 0x388; static int numChannels = 8; diff --git a/src/setup/txt_joybinput.c b/src/setup/txt_joybinput.c index cde3d2c2..9ad26a45 100644 --- a/src/setup/txt_joybinput.c +++ b/src/setup/txt_joybinput.c @@ -48,7 +48,12 @@ static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_input)) if (event->type == SDL_JOYBUTTONDOWN) { *joystick_input->variable = event->jbutton.button; - TXT_EmitSignal(joystick_input, "set"); + + if (joystick_input->check_conflicts) + { + TXT_EmitSignal(joystick_input, "set"); + } + TXT_CloseWindow(joystick_input->prompt_window); return 1; } @@ -89,6 +94,10 @@ static void OpenPromptWindow(txt_joystick_input_t *joystick_input) txt_label_t *label; SDL_Joystick *joystick; + // Silently update when the shift button is held down. + + joystick_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + if (SDL_Init(SDL_INIT_JOYSTICK) < 0) { return; @@ -153,15 +162,7 @@ static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input), int selected GetJoystickButtonDescription(*joystick_input->variable, buf); } - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - else - { - TXT_BGColor(TXT_COLOR_BLUE, 0); - } - + TXT_SetWidgetBG(joystick_input, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/src/setup/txt_joybinput.h b/src/setup/txt_joybinput.h index b2920b88..69ec4a1f 100644 --- a/src/setup/txt_joybinput.h +++ b/src/setup/txt_joybinput.h @@ -37,6 +37,7 @@ struct txt_joystick_input_s txt_widget_t widget; int *variable; txt_window_t *prompt_window; + int check_conflicts; }; txt_joystick_input_t *TXT_NewJoystickInput(int *variable); diff --git a/src/setup/txt_keyinput.c b/src/setup/txt_keyinput.c index 08eb9d8c..6f1ee4dd 100644 --- a/src/setup/txt_keyinput.c +++ b/src/setup/txt_keyinput.c @@ -42,7 +42,12 @@ static int KeyPressCallback(txt_window_t *window, int key, // Got the key press. Save to the variable and close the window. *key_input->variable = key; - TXT_EmitSignal(key_input, "set"); + + if (key_input->check_conflicts) + { + TXT_EmitSignal(key_input, "set"); + } + TXT_CloseWindow(window); // Re-enable key mappings now that we have the key @@ -67,6 +72,10 @@ static void OpenPromptWindow(txt_key_input_t *key_input) txt_window_t *window; txt_label_t *label; + // Silently update when the shift button is held down. + + key_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + window = TXT_NewWindow(NULL); TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); TXT_SetWindowAction(window, TXT_HORIZ_CENTER, @@ -118,15 +127,7 @@ static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input), int selected) TXT_GetKeyDescription(*key_input->variable, buf); } - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - else - { - TXT_BGColor(TXT_COLOR_BLUE, 0); - } - + TXT_SetWidgetBG(key_input, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/src/setup/txt_keyinput.h b/src/setup/txt_keyinput.h index 4952a970..5df0b2e3 100644 --- a/src/setup/txt_keyinput.h +++ b/src/setup/txt_keyinput.h @@ -35,6 +35,7 @@ struct txt_key_input_s { txt_widget_t widget; int *variable; + int check_conflicts; }; txt_key_input_t *TXT_NewKeyInput(int *variable); diff --git a/src/setup/txt_mouseinput.c b/src/setup/txt_mouseinput.c index 4f454c8c..c3e17299 100644 --- a/src/setup/txt_mouseinput.c +++ b/src/setup/txt_mouseinput.c @@ -42,7 +42,12 @@ static int MousePressCallback(txt_window_t *window, // Got the mouse press. Save to the variable and close the window. *mouse_input->variable = b - TXT_MOUSE_BASE; - TXT_EmitSignal(mouse_input, "set"); + + if (mouse_input->check_conflicts) + { + TXT_EmitSignal(mouse_input, "set"); + } + TXT_CloseWindow(window); return 1; @@ -53,6 +58,9 @@ static void OpenPromptWindow(txt_mouse_input_t *mouse_input) txt_window_t *window; txt_label_t *label; + // Silently update when the shift key is held down. + mouse_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + window = TXT_NewWindow(NULL); TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); TXT_SetWindowAction(window, TXT_HORIZ_CENTER, @@ -111,15 +119,7 @@ static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input), int selected) GetMouseButtonDescription(*mouse_input->variable, buf); } - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - else - { - TXT_BGColor(TXT_COLOR_BLUE, 0); - } - + TXT_SetWidgetBG(mouse_input, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(buf); diff --git a/src/setup/txt_mouseinput.h b/src/setup/txt_mouseinput.h index 57c258eb..ef3ec2aa 100644 --- a/src/setup/txt_mouseinput.h +++ b/src/setup/txt_mouseinput.h @@ -35,6 +35,7 @@ struct txt_mouse_input_s { txt_widget_t widget; int *variable; + int check_conflicts; }; txt_mouse_input_t *TXT_NewMouseInput(int *variable); diff --git a/textscreen/txt_button.c b/textscreen/txt_button.c index 85517b3d..536e5f56 100644 --- a/textscreen/txt_button.c +++ b/textscreen/txt_button.c @@ -46,16 +46,12 @@ static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button), int selected) w = button->widget.w; - TXT_BGColor(TXT_COLOR_BLUE, 0); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } + TXT_SetWidgetBG(button, selected); TXT_DrawString(button->label); - + for (i=strlen(button->label); i < w; ++i) { TXT_DrawString(" "); diff --git a/textscreen/txt_checkbox.c b/textscreen/txt_checkbox.c index 35c5739d..f2183b7c 100644 --- a/textscreen/txt_checkbox.c +++ b/textscreen/txt_checkbox.c @@ -48,7 +48,7 @@ static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int selected) w = checkbox->widget.w; - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); TXT_DrawString("("); @@ -67,11 +67,7 @@ static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox), int selected) TXT_DrawString(") "); - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - + TXT_SetWidgetBG(checkbox, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(checkbox->label); diff --git a/textscreen/txt_desktop.c b/textscreen/txt_desktop.c index f833441f..c497f0e3 100644 --- a/textscreen/txt_desktop.c +++ b/textscreen/txt_desktop.c @@ -61,6 +61,16 @@ void TXT_RemoveDesktopWindow(txt_window_t *win) num_windows = to; } +txt_window_t *TXT_GetActiveWindow(void) +{ + if (num_windows == 0) + { + return NULL; + } + + return all_windows[num_windows - 1]; +} + static void DrawDesktopBackground(const char *title) { int i; diff --git a/textscreen/txt_desktop.h b/textscreen/txt_desktop.h index 95343977..42a011e7 100644 --- a/textscreen/txt_desktop.h +++ b/textscreen/txt_desktop.h @@ -63,6 +63,15 @@ void TXT_ExitMainLoop(void); void TXT_GUIMainLoop(void); +/** + * Get the top window on the desktop that is currently receiving + * inputs. + * + * @return The active window, or NULL if no windows are present. + */ + +txt_window_t *TXT_GetActiveWindow(void); + #endif /* #ifndef TXT_DESKTOP_H */ diff --git a/textscreen/txt_dropdown.c b/textscreen/txt_dropdown.c index c8103302..c9a5d015 100644 --- a/textscreen/txt_dropdown.c +++ b/textscreen/txt_dropdown.c @@ -99,6 +99,22 @@ static int SelectorWindowListener(txt_window_t *window, int key, void *user_data return 0; } +static int SelectorMouseListener(txt_window_t *window, int x, int y, int b, + void *unused) +{ + txt_widget_t *win; + + win = (txt_widget_t *) window; + + if (x < win->x || x > win->x + win->w || y < win->y || y > win->y + win->h) + { + TXT_CloseWindow(window); + return 1; + } + + return 0; +} + // Open the dropdown list window to select an item static void OpenSelectorWindow(txt_dropdown_list_t *list) @@ -158,6 +174,7 @@ static void OpenSelectorWindow(txt_dropdown_list_t *list) // Catch presses of escape in this window and close it. TXT_SetKeyListener(window, SelectorWindowListener, NULL); + TXT_SetMouseListener(window, SelectorMouseListener, NULL); } static int DropdownListWidth(txt_dropdown_list_t *list) @@ -197,15 +214,7 @@ static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list), int selected) // Set bg/fg text colors. - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - else - { - TXT_BGColor(TXT_COLOR_BLUE, 0); - } - + TXT_SetWidgetBG(list, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); // Select a string to draw from the list, if the current value is diff --git a/textscreen/txt_gui.c b/textscreen/txt_gui.c index ec166415..d00e3a65 100644 --- a/textscreen/txt_gui.c +++ b/textscreen/txt_gui.c @@ -131,7 +131,7 @@ void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h) int bx, by; TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); for (y1=y; y1<y+h; ++y1) { @@ -191,7 +191,7 @@ void TXT_DrawSeparator(int x, int y, int w) data = TXT_GetScreenData(); TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); if (!VALID_Y(y)) { diff --git a/textscreen/txt_gui.h b/textscreen/txt_gui.h index ad7ae428..06fc7a36 100644 --- a/textscreen/txt_gui.h +++ b/textscreen/txt_gui.h @@ -27,6 +27,9 @@ #ifndef TXT_GUI_H #define TXT_GUI_H +#define TXT_WINDOW_BACKGROUND TXT_COLOR_BLUE +#define TXT_HOVER_BACKGROUND TXT_COLOR_CYAN + void TXT_DrawDesktopBackground(const char *title); void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h); void TXT_DrawSeparator(int x, int y, int w); @@ -35,6 +38,7 @@ void TXT_DrawString(const char *s); void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range); void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range); + void TXT_InitClipArea(void); void TXT_PushClipArea(int x1, int x2, int y1, int y2); void TXT_PopClipArea(void); diff --git a/textscreen/txt_inputbox.c b/textscreen/txt_inputbox.c index 852346f3..a28c342c 100644 --- a/textscreen/txt_inputbox.c +++ b/textscreen/txt_inputbox.c @@ -60,15 +60,9 @@ static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox), int selected) { TXT_BGColor(TXT_COLOR_BLACK, 0); } - else if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } else { - // Not even selected - - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_SetWidgetBG(inputbox, selected); } TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); diff --git a/textscreen/txt_label.c b/textscreen/txt_label.c index 0deea803..c973bce2 100644 --- a/textscreen/txt_label.c +++ b/textscreen/txt_label.c @@ -176,7 +176,7 @@ txt_label_t *TXT_NewLabel(char *text) // Default colors - label->bgcolor = TXT_COLOR_BLUE; + label->bgcolor = TXT_WINDOW_BACKGROUND; label->fgcolor = TXT_COLOR_BRIGHT_WHITE; TXT_SetLabel(label, text); diff --git a/textscreen/txt_main.h b/textscreen/txt_main.h index add30fa3..a415ee1b 100644 --- a/textscreen/txt_main.h +++ b/textscreen/txt_main.h @@ -34,10 +34,12 @@ // Special keypress values that correspond to mouse button clicks -#define TXT_MOUSE_BASE 0x10000 -#define TXT_MOUSE_LEFT (TXT_MOUSE_BASE + 0) -#define TXT_MOUSE_RIGHT (TXT_MOUSE_BASE + 1) -#define TXT_MOUSE_MIDDLE (TXT_MOUSE_BASE + 2) +#define TXT_MOUSE_BASE 0x10000 +#define TXT_MOUSE_LEFT (TXT_MOUSE_BASE + 0) +#define TXT_MOUSE_RIGHT (TXT_MOUSE_BASE + 1) +#define TXT_MOUSE_MIDDLE (TXT_MOUSE_BASE + 2) +#define TXT_MOUSE_SCROLLUP (TXT_MOUSE_BASE + 3) +#define TXT_MOUSE_SCROLLDOWN (TXT_MOUSE_BASE + 4) #define TXT_MAX_MOUSE_BUTTONS 16 // Screen size @@ -67,6 +69,16 @@ typedef enum TXT_COLOR_BRIGHT_WHITE, } txt_color_t; +// Modifier keys. + +typedef enum +{ + TXT_MOD_SHIFT, + TXT_MOD_CTRL, + TXT_MOD_ALT, + TXT_NUM_MODIFIERS +} txt_modifier_t; + // Initialize the screen // Returns 1 if successful, 0 if failed. @@ -92,6 +104,10 @@ void TXT_UpdateScreen(void); int TXT_GetChar(void); +// Read the current state of modifier keys that are held down. + +int TXT_GetModifierState(txt_modifier_t mod); + // Provides a short description of a key code, placing into the // provided buffer. diff --git a/textscreen/txt_radiobutton.c b/textscreen/txt_radiobutton.c index 00c2c4fc..0755562d 100644 --- a/textscreen/txt_radiobutton.c +++ b/textscreen/txt_radiobutton.c @@ -48,7 +48,7 @@ static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int selected) w = radiobutton->widget.w; - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); TXT_DrawString("("); @@ -67,11 +67,7 @@ static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton), int selected) TXT_DrawString(") "); - if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } - + TXT_SetWidgetBG(radiobutton, selected); TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(radiobutton->label); diff --git a/textscreen/txt_scrollpane.c b/textscreen/txt_scrollpane.c index 17c9bcbf..2fd45c55 100644 --- a/textscreen/txt_scrollpane.c +++ b/textscreen/txt_scrollpane.c @@ -416,6 +416,33 @@ static void TXT_ScrollPaneMousePress(TXT_UNCAST_ARG(scrollpane), scrollbars = NeedsScrollbars(scrollpane); + if (b == TXT_MOUSE_SCROLLUP) + { + if (scrollbars & SCROLLBAR_VERTICAL) + { + scrollpane->y -= 3; + } + else if (scrollbars & SCROLLBAR_HORIZONTAL) + { + scrollpane->x -= 3; + } + + return; + } + else if (b == TXT_MOUSE_SCROLLDOWN) + { + if (scrollbars & SCROLLBAR_VERTICAL) + { + scrollpane->y += 3; + } + else if (scrollbars & SCROLLBAR_HORIZONTAL) + { + scrollpane->x += 3; + } + + return; + } + rel_x = x - scrollpane->widget.x; rel_y = y - scrollpane->widget.y; @@ -433,14 +460,15 @@ static void TXT_ScrollPaneMousePress(TXT_UNCAST_ARG(scrollpane), else { int range = FullWidth(scrollpane) - scrollpane->w; + int bar_max = scrollpane->w - 3; - scrollpane->x = ((rel_x - 1) * range) / (scrollpane->w - 3); + scrollpane->x = ((rel_x - 1) * range + (bar_max / 2)) / bar_max; } return; } - // Click on the horizontal scrollbar? + // Click on the vertical scrollbar? if ((scrollbars & SCROLLBAR_VERTICAL) && rel_x == scrollpane->w) { if (rel_y == 0) @@ -454,8 +482,9 @@ static void TXT_ScrollPaneMousePress(TXT_UNCAST_ARG(scrollpane), else { int range = FullHeight(scrollpane) - scrollpane->h; + int bar_max = scrollpane->h - 3; - scrollpane->y = ((rel_y - 1) * range) / (scrollpane->h - 3); + scrollpane->y = ((rel_y - 1) * range + (bar_max / 2)) / bar_max; } return; @@ -465,7 +494,6 @@ static void TXT_ScrollPaneMousePress(TXT_UNCAST_ARG(scrollpane), { TXT_WidgetMousePress(scrollpane->child, x, y, b); } - } static void TXT_ScrollPaneLayout(TXT_UNCAST_ARG(scrollpane)) @@ -529,6 +557,10 @@ txt_scrollpane_t *TXT_NewScrollPane(int w, int h, TXT_UNCAST_ARG(target)) scrollpane->expand_w = w <= 0; scrollpane->expand_h = h <= 0; + // Set parent pointer for inner widget. + + target->parent = &scrollpane->widget; + return scrollpane; } diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c index 2fbaa316..477fdb52 100644 --- a/textscreen/txt_sdl.c +++ b/textscreen/txt_sdl.c @@ -63,6 +63,8 @@ static int key_mapping = 1; static TxtSDLEventCallbackFunc event_callback; static void *event_callback_data; +static int modifier_state[TXT_NUM_MODIFIERS]; + // Font we are using: static txt_font_t *font; @@ -225,7 +227,7 @@ int TXT_Init(void) // Ignore all mouse motion events - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); +// SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // Repeat key presses so we can hold down arrows to scroll down the // menu, for example. This is what setup.exe does. @@ -479,6 +481,66 @@ static int SDLButtonToTXTButton(int button) } } +static int MouseHasMoved(void) +{ + static int last_x = 0, last_y = 0; + int x, y; + + TXT_GetMousePosition(&x, &y); + + if (x != last_x || y != last_y) + { + last_x = x; last_y = y; + return 1; + } + else + { + return 0; + } +} + +// Examine a key press/release and update the modifier key state +// if necessary. + +static void UpdateModifierState(SDL_keysym *sym, int pressed) +{ + txt_modifier_t mod; + + switch (sym->sym) + { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + mod = TXT_MOD_SHIFT; + break; + + case SDLK_LCTRL: + case SDLK_RCTRL: + mod = TXT_MOD_CTRL; + break; + + case SDLK_LALT: + case SDLK_RALT: +#if !SDL_VERSION_ATLEAST(1, 3, 0) + case SDLK_LMETA: + case SDLK_RMETA: +#endif + mod = TXT_MOD_ALT; + break; + + default: + return; + } + + if (pressed) + { + ++modifier_state[mod]; + } + else + { + --modifier_state[mod]; + } +} + signed int TXT_GetChar(void) { SDL_Event ev; @@ -508,12 +570,24 @@ signed int TXT_GetChar(void) break; case SDL_KEYDOWN: + UpdateModifierState(&ev.key.keysym, 1); + return TranslateKey(&ev.key.keysym); + case SDL_KEYUP: + UpdateModifierState(&ev.key.keysym, 0); + break; + case SDL_QUIT: // Quit = escape return 27; + case SDL_MOUSEMOTION: + if (MouseHasMoved()) + { + return 0; + } + default: break; } @@ -522,6 +596,16 @@ signed int TXT_GetChar(void) return -1; } +int TXT_GetModifierState(txt_modifier_t mod) +{ + if (mod < TXT_NUM_MODIFIERS) + { + return modifier_state[mod] > 0; + } + + return 0; +} + static const char *SpecialKeyName(int key) { switch (key) diff --git a/textscreen/txt_separator.c b/textscreen/txt_separator.c index 6b779626..89db0b03 100644 --- a/textscreen/txt_separator.c +++ b/textscreen/txt_separator.c @@ -65,7 +65,7 @@ static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator), int selected) { TXT_GotoXY(x, y); - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); TXT_FGColor(TXT_COLOR_BRIGHT_GREEN); TXT_DrawString(" "); TXT_DrawString(separator->label); @@ -80,6 +80,20 @@ static void TXT_SeparatorDestructor(TXT_UNCAST_ARG(separator)) free(separator->label); } +void TXT_SetSeparatorLabel(txt_separator_t *separator, char *label) +{ + free(separator->label); + + if (label != NULL) + { + separator->label = strdup(label); + } + else + { + separator->label = NULL; + } +} + txt_widget_class_t txt_separator_class = { TXT_NeverSelectable, @@ -99,14 +113,8 @@ txt_separator_t *TXT_NewSeparator(char *label) TXT_InitWidget(separator, &txt_separator_class); - if (label != NULL) - { - separator->label = strdup(label); - } - else - { - separator->label = NULL; - } + separator->label = NULL; + TXT_SetSeparatorLabel(separator, label); return separator; } diff --git a/textscreen/txt_separator.h b/textscreen/txt_separator.h index 2f2331da..f693d70e 100644 --- a/textscreen/txt_separator.h +++ b/textscreen/txt_separator.h @@ -59,6 +59,14 @@ extern txt_widget_class_t txt_separator_class; txt_separator_t *TXT_NewSeparator(char *label); -#endif /* #ifndef TXT_SEPARATOR_H */ +/** + * Change the label on a separator. + * + * @param separator The separator. + * @param label The new label. + */ + +void TXT_SetSeparatorLabel(txt_separator_t *separator, char *label); +#endif /* #ifndef TXT_SEPARATOR_H */ diff --git a/textscreen/txt_spinctrl.c b/textscreen/txt_spinctrl.c index d775aecf..2b2d4d09 100644 --- a/textscreen/txt_spinctrl.c +++ b/textscreen/txt_spinctrl.c @@ -149,7 +149,7 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected) unsigned int padding; TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); TXT_DrawString("\x1b "); @@ -161,13 +161,9 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected) { TXT_BGColor(TXT_COLOR_BLACK, 0); } - else if (selected) - { - TXT_BGColor(TXT_COLOR_GREY, 0); - } else { - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_SetWidgetBG(spincontrol, selected); } if (!spincontrol->editing) @@ -195,7 +191,7 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected) } TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); - TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); TXT_DrawString(" \x1a"); } diff --git a/textscreen/txt_table.c b/textscreen/txt_table.c index ffe6fd14..7a8624f0 100644 --- a/textscreen/txt_table.c +++ b/textscreen/txt_table.c @@ -173,6 +173,13 @@ void TXT_AddWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget)) sizeof(txt_widget_t *) * (table->num_widgets + 1)); table->widgets[table->num_widgets] = widget; ++table->num_widgets; + + // Maintain parent pointer. + + if (widget != NULL) + { + widget->parent = &table->widget; + } } // Add multiple widgets to a table. diff --git a/textscreen/txt_widget.c b/textscreen/txt_widget.c index 760943d5..d47a7507 100644 --- a/textscreen/txt_widget.c +++ b/textscreen/txt_widget.c @@ -24,6 +24,8 @@ #include "txt_io.h" #include "txt_widget.h" +#include "txt_gui.h" +#include "txt_desktop.h" typedef struct { @@ -82,6 +84,7 @@ void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class) widget->widget_class = widget_class; widget->callback_table = TXT_NewCallbackTable(); + widget->parent = NULL; // Visible by default. @@ -237,3 +240,62 @@ int TXT_SelectableWidget(TXT_UNCAST_ARG(widget)) } } +int TXT_ContainsWidget(TXT_UNCAST_ARG(haystack), TXT_UNCAST_ARG(needle)) +{ + TXT_CAST_ARG(txt_widget_t, haystack); + TXT_CAST_ARG(txt_widget_t, needle); + + while (needle != NULL) + { + if (needle == haystack) + { + return 1; + } + + needle = needle->parent; + } + + return 0; +} + +int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget)) +{ + TXT_CAST_ARG(txt_widget_t, widget); + txt_window_t *active_window; + int x, y; + + // We can only be hovering over widgets in the active window. + + active_window = TXT_GetActiveWindow(); + + if (active_window == NULL || !TXT_ContainsWidget(active_window, widget)) + { + return 0; + } + + // Is the mouse cursor within the bounds of the widget? + + TXT_GetMousePosition(&x, &y); + + return (x >= widget->x && x < widget->x + widget->w + && y >= widget->y && y < widget->y + widget->h); +} + +void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget), int selected) +{ + TXT_CAST_ARG(txt_widget_t, widget); + + if (selected) + { + TXT_BGColor(TXT_COLOR_GREY, 0); + } + else if (TXT_HoveringOverWidget(widget)) + { + TXT_BGColor(TXT_HOVER_BACKGROUND, 0); + } + else + { + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); + } +} + diff --git a/textscreen/txt_widget.h b/textscreen/txt_widget.h index bb895f92..ebb5a292 100644 --- a/textscreen/txt_widget.h +++ b/textscreen/txt_widget.h @@ -102,6 +102,10 @@ struct txt_widget_s int x, y; unsigned int w, h; + + // Pointer up to parent widget that contains this widget. + + txt_widget_t *parent; }; void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class); @@ -146,6 +150,34 @@ void TXT_SetWidgetAlign(TXT_UNCAST_ARG(widget), txt_horiz_align_t horiz_align); int TXT_SelectableWidget(TXT_UNCAST_ARG(widget)); -#endif /* #ifndef TXT_WIDGET_H */ +/** + * Query whether the mouse is hovering over the specified widget. + * + * @param widget The widget. + * @return Non-zero if the mouse cursor is over the widget. + */ + +int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget)); + +/** + * Set the background to draw the specified widget, depending on + * whether it is selected and the mouse is hovering over it. + * + * @param widget The widget. + * @param selected Whether the widget is selected. + */ + +void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget), int selected); + +/** + * Query whether the specified widget is contained within another + * widget. + * + * @param haystack The widget that might contain needle. + * @param needle The widget being queried. + */ +int TXT_ContainsWidget(TXT_UNCAST_ARG(haystack), TXT_UNCAST_ARG(needle)); + +#endif /* #ifndef TXT_WIDGET_H */ diff --git a/textscreen/txt_window.c b/textscreen/txt_window.c index 46e71d3a..cd8a6c7a 100644 --- a/textscreen/txt_window.c +++ b/textscreen/txt_window.c @@ -40,6 +40,13 @@ void TXT_SetWindowAction(txt_window_t *window, } window->actions[position] = action; + + // Maintain parent pointer. + + if (action != NULL) + { + action->widget.parent = &window->table.widget; + } } txt_window_t *TXT_NewWindow(char *title) @@ -158,7 +165,7 @@ static void LayoutActionArea(txt_window_t *window) TXT_CalcWidgetSize(widget); - widget->x = window->window_x + 2; + widget->x = window->window_x + 1; widget->y = window->window_y + window->window_h - widget->h - 1; // Adjust available space: @@ -175,7 +182,7 @@ static void LayoutActionArea(txt_window_t *window) TXT_CalcWidgetSize(widget); - widget->x = window->window_x + window->window_w - 2 - widget->w; + widget->x = window->window_x + window->window_w - 1 - widget->w; widget->y = window->window_y + window->window_h - widget->h - 1; // Adjust available space: @@ -220,7 +227,7 @@ static void CalcActionAreaSize(txt_window_t *window, txt_widget_t *widget; int i; - *w = 1; + *w = 0; *h = 0; // Calculate the width of all the action widgets and use this @@ -233,7 +240,7 @@ static void CalcActionAreaSize(txt_window_t *window, if (widget != NULL) { TXT_CalcWidgetSize(widget); - *w += widget->w + 1; + *w += widget->w; if (widget->h > *h) { diff --git a/textscreen/txt_window_action.c b/textscreen/txt_window_action.c index e593b7b6..df0e4ea3 100644 --- a/textscreen/txt_window_action.c +++ b/textscreen/txt_window_action.c @@ -37,9 +37,10 @@ static void TXT_WindowActionSizeCalc(TXT_UNCAST_ARG(action)) TXT_GetKeyDescription(action->key, buf); - // Minimum width is the string length + two spaces for padding + // Width is label length, plus key description length, plus '=' + // and two surrounding spaces. - action->widget.w = strlen(action->label) + strlen(buf) + 1; + action->widget.w = strlen(action->label) + strlen(buf) + 3; action->widget.h = 1; } @@ -50,12 +51,24 @@ static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action), int selected) TXT_GetKeyDescription(action->key, buf); + if (TXT_HoveringOverWidget(action)) + { + TXT_BGColor(TXT_COLOR_BLACK, 0); + } + else + { + TXT_BGColor(TXT_WINDOW_BACKGROUND, 0); + } + + TXT_DrawString(" "); TXT_FGColor(TXT_COLOR_BRIGHT_GREEN); TXT_DrawString(buf); TXT_FGColor(TXT_COLOR_BRIGHT_CYAN); TXT_DrawString("="); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); TXT_DrawString(action->label); + TXT_DrawString(" "); } static void TXT_WindowActionDestructor(TXT_UNCAST_ARG(action)) @@ -69,7 +82,7 @@ static int TXT_WindowActionKeyPress(TXT_UNCAST_ARG(action), int key) { TXT_CAST_ARG(txt_window_action_t, action); - if (key == action->key) + if (tolower(key) == tolower(action->key)) { TXT_EmitSignal(action, "pressed"); return 1; |