summaryrefslogtreecommitdiff
path: root/app/help
diff options
context:
space:
mode:
Diffstat (limited to 'app/help')
-rw-r--r--app/help/CMakeLists.txt27
-rw-r--r--app/help/ChangeLog63
-rw-r--r--app/help/fixbmp.c227
-rw-r--r--app/help/genhelp.c212
-rw-r--r--app/help/genhelp.in705
-rw-r--r--app/help/genmessages.c339
-rw-r--r--app/help/messages.in1426
-rwxr-xr-xapp/help/mkpngbutt21
-rwxr-xr-xapp/help/mkpngs88
-rw-r--r--app/help/mkshg.c455
-rwxr-xr-xapp/help/mkshgs348
-rw-r--r--app/help/mkxpmbutt.c303
-rw-r--r--app/help/pageorder.c48
-rw-r--r--app/help/prochelp.c2178
-rw-r--r--app/help/readpng.c275
-rw-r--r--app/help/readpng.h64
-rw-r--r--app/help/xtrkcad.info1101
-rw-r--r--app/help/xtrkcad.tip235
-rw-r--r--app/help/xvfontsel.hlpsrc25
-rw-r--r--app/help/xvprintsel.hlpsrc73
20 files changed, 8213 insertions, 0 deletions
diff --git a/app/help/CMakeLists.txt b/app/help/CMakeLists.txt
new file mode 100644
index 0000000..2b7efa7
--- /dev/null
+++ b/app/help/CMakeLists.txt
@@ -0,0 +1,27 @@
+PROJECT(help)
+
+ADD_EXECUTABLE(genhelp genhelp.c)
+
+ADD_EXECUTABLE(genmessages genmessages.c)
+GET_TARGET_PROPERTY(genmessages_EXE genmessages LOCATION)
+
+IF(XTRKCAD_USE_GETTEXT)
+ SET(GENMESSAGES_OPTS "-i18n")
+ELSE(XTRKCAD_USE_GETTEXT)
+ SET(GENMESSAGES_OPTS "")
+ENDIF(XTRKCAD_USE_GETTEXT)
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/messages.h ${CMAKE_CURRENT_BINARY_DIR}/messages.but
+ DEPENDS genmessages ${CMAKE_CURRENT_SOURCE_DIR}/messages.in
+ COMMAND ${genmessages_EXE} ${GENMESSAGES_OPTS} ${CMAKE_CURRENT_SOURCE_DIR}/messages.in ${CMAKE_CURRENT_BINARY_DIR}/messages.but
+ )
+
+ADD_CUSTOM_TARGET(Help ALL
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/messages.h ${CMAKE_CURRENT_BINARY_DIR}/messages.but
+ )
+
+INSTALL(
+ FILES xtrkcad.tip
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}
+ )
diff --git a/app/help/ChangeLog b/app/help/ChangeLog
new file mode 100644
index 0000000..439dcd7
--- /dev/null
+++ b/app/help/ChangeLog
@@ -0,0 +1,63 @@
+Jun 10, 2009
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c: fix bug with whitespace-only strings
+
+Jun 09, 2009
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c: add include file for issspace()
+
+Jun 08, 2009
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c: fixed problem with line endings, correct warning
+ for the but output file
+
+Aug 29, 2008
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ genhelp.in: fixed typo
+
+Feb 03, 2008
+ ENH: Martin Fischer <m_fischer@users.sourceforge.net>
+ messages.in: added tooltip for new option 'onstartup'
+
+Jan 27, 2008
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ messages.in: new product name is XTrackCAD
+ genmessages.c: added warning remark to generated include file
+
+Jan 21, 2008
+ FIX: Mikko Nissinen <mni77@users.sourceforge.net>
+ messages.in: MSG_2ND_TRK_NOT_SEL_UNSEL -> "...%sselected" changed
+ to "...%s" for internationalization reasons.
+
+Jan 03. 2008
+ IMPROVEMENT: Martin Fischer
+ genmessages.c: added warning message
+
+Dec 09, 2007
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c: corrected parsing problems
+
+Dec 03, 2007
+ FIX: Bob Blackwell
+ genmessages.in: corrected spelling errors
+
+Dec 02, 2007
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c: changed created halibut format
+
+Nov 23, 2007
+ FIX: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c, Fixed handling of \n escape sequence in header file output
+
+Nov 22, 2007
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ genmessages.c, Makefile, messages.in: build messages in Halibut format
+
+Nov 12, 2007
+ FIX: Mikko Nissinen <mni77@users.sourceforge.net>
+ genhelp.c: Changed internationalization header file name from xtci18n.h to
+ i18n.h.
+
+Nov 10, 2007
+ IMPROVEMENT: Martin Fischer <m_fischer@users.sourceforge.net>
+ genhelp.c: Added option to create gettext enabled C source.
diff --git a/app/help/fixbmp.c b/app/help/fixbmp.c
new file mode 100644
index 0000000..44555dc
--- /dev/null
+++ b/app/help/fixbmp.c
@@ -0,0 +1,227 @@
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+
+#define TRUE (1)
+#define FALSE (0)
+
+struct BITMAPFILEHEADER {
+ char bfType[2];
+ long bfSize;
+ short bfRsvd1;
+ short bfRsvd2;
+ long bfOffBits;
+ };
+
+struct BITMAPINFOHEADER {
+ long biSize;
+ long biWidth;
+ long biHeight;
+ short biPlanes;
+ short biBitCount;
+ long biCompression;
+ long biSizeImage;
+ long biXPelsPerMeter;
+ long biYPelsPerMeter;
+ long biClrUsed;
+ long biClrImportant;
+ };
+
+int namenames;
+int dumpInfo;
+int dumpColorMap;
+int dumpBits;
+int dumpHisto;
+int updateColorCount;
+int zeroColorCount;
+int setColorCount;
+int fixColorMap;
+
+int fixbmp( char * filename )
+{
+ FILE * file;
+ struct BITMAPFILEHEADER bmfh;
+ struct BITMAPINFOHEADER bmih;
+ int rc;
+ long colors[256];
+ int i, j, size;
+ unsigned char * bmp, bit;
+ int colorCnt;
+ long maxcolor;
+ long histo[256];;
+
+ if ( namenames )
+ printf( "%s\n", filename );
+ file = fopen( filename, "r+" );
+ if ( file == NULL ) {
+ fprintf( stderr, "%s: Cant open:%s\n", filename, filename );
+ return FALSE;
+ }
+ rc = fread( &bmfh.bfType, 1, sizeof bmfh.bfType, file );
+ rc += fread( &bmfh.bfSize, 1, sizeof bmfh.bfSize, file );
+ rc += fread( &bmfh.bfRsvd1, 1, sizeof bmfh.bfRsvd1, file );
+ rc += fread( &bmfh.bfRsvd2, 1, sizeof bmfh.bfRsvd2, file );
+ rc += fread( &bmfh.bfOffBits, 1, sizeof bmfh.bfOffBits, file );
+ if ( rc != 14 ) {
+ fprintf( stderr, "%s: Bad read of bmfh: %d\n", filename, rc );
+ return FALSE;
+ }
+ rc = fread( &bmih, 1, sizeof bmih, file );
+ if ( rc != sizeof bmih ) {
+ fprintf( stderr, "%s: Bad read of bmih: %d\n", filename, rc );
+ return FALSE;
+ }
+ if ( dumpInfo ) {
+ printf( "fh:sz=%d, off=%ld\n", bmfh.bfSize, bmfh.bfOffBits );
+ printf( "ih:sz=%ld, w=%ld, h=%ld, (%ld), pl=%d, bc=%d, co=%ld, si=%ld, cu=%ld, ci=%ld\n",
+ bmih.biSize, bmih.biWidth, bmih.biHeight, bmih.biWidth*bmih.biHeight,
+ bmih.biPlanes, bmih.biBitCount, bmih.biCompression,
+ bmih.biSizeImage, bmih.biClrUsed, bmih.biClrImportant );
+ }
+ if ( bmih.biPlanes != 1 || bmih.biBitCount != 8 ) {
+ fprintf( stderr, "%s: bad Planes(%d) or BitCount(%d)\n", filename, bmih.biPlanes, bmih.biBitCount );
+ return FALSE;
+ }
+ if ( bmih.biClrUsed > 256 ) {
+ fprintf( stderr, "%s: Too many colors (%ld)\n", filename, bmih.biClrUsed );
+ return FALSE;
+ }
+ colorCnt = bmih.biClrUsed;
+ if ( colorCnt == 0 )
+ colorCnt = 256;
+ rc = fread( colors, sizeof colors[0], colorCnt, file );
+ if ( rc != colorCnt ) {
+ fprintf( stderr, "%s: Bad read of colors: %d\n", filename, rc );
+ return FALSE;
+ }
+ if ( dumpColorMap ) {
+ printf( "colorcnt=%d", rc );
+ for ( i=0; i<colorCnt; i++ ) {
+ if ( i%8 == 0 )
+ printf( "\n%2.2x: ", i );
+ printf( "%8.8lx ", colors[i] );
+ }
+ printf( "\n" );
+ }
+ if ( fixColorMap ) {
+ long c;
+ for ( i=0; i<colorCnt; i++ ) {
+ c = colors[i]&0xFFFFFF;
+ if ( (c & 0xFF0000) != 0xFF0000 )
+ c &= 0xF0FFFF;
+ if ( (c & 0x00FF00) != 0x00FF00 )
+ c &= 0xFFF0FF;
+ if ( (c & 0x0000FF) != 0x0000FF )
+ c &= 0xFFFFF0;
+ colors[i] = c;
+ }
+ fseek( file, 14+40, SEEK_SET );
+ rc = fwrite( colors, sizeof colors[0], colorCnt, file );
+ if ( rc != colorCnt ) {
+ fprintf( stderr, "%s: Bad write of colors: %d\n", filename, rc );
+ return FALSE;
+ }
+ }
+ size = (int)(bmih.biWidth*bmih.biHeight);
+ size = (int)bmih.biWidth;
+ size = (size+3)/4*4;
+ fseek( file, bmfh.bfOffBits, SEEK_SET );
+ bmp = (unsigned char*)malloc( size );
+ if ( bmp == NULL ) {
+ fprintf( stderr, "%s: Cant malloc(%d) for bitmap\n", filename, size );
+ return FALSE;
+ }
+ maxcolor = 0;
+ memset( histo, 0, sizeof histo );
+ for ( j=0; j<bmih.biHeight; j++ ) {
+ rc = fread( bmp, 1, size, file );
+ if ( rc != size ) {
+ fprintf( stderr, "%s: Cant read bits for line %d: %d\n", filename, j, rc );
+ return FALSE;
+ }
+ if ( dumpBits )
+ printf( "%2.2d: ", j );
+ for ( i=0; i<bmih.biWidth; i++ ) {
+ bit = bmp[i];
+ histo[bit]++;
+ if ( dumpBits )
+ printf( "%2.2x", bit );
+ if ( bit > maxcolor )
+ maxcolor = bit;
+ }
+ if ( dumpBits )
+ printf( "\n" );
+ }
+ free( bmp );
+ if ( dumpHisto ) {
+ printf( "maxcolor=%ld\n", maxcolor );
+ for ( i=0; i<256; i++ )
+ if ( histo[i] )
+ printf( "[%2.2x]%8.8x = %ld\n", i, colors[i], histo[i] );
+
+ }
+ if ( updateColorCount || zeroColorCount || setColorCount ) {
+ fseek( file, 14, SEEK_SET );
+ if ( updateColorCount ) {
+ bmih.biClrImportant = maxcolor;
+ } else if ( zeroColorCount ) {
+ bmih.biClrImportant = 0;
+ bmih.biClrUsed = 0;
+ } else {
+ bmih.biClrImportant = 256;
+ bmih.biClrUsed = 256;
+ }
+ rc = fwrite( &bmih, 1, sizeof bmih, file );
+ if ( rc != sizeof bmih ) {
+ fprintf( stderr, "%s: Update failed; %d\n", filename, rc );
+ }
+ }
+ fclose( file );
+ return TRUE;
+}
+
+
+int main( int argc, char * argv[] )
+{
+ while ( argc > 2 && argv[1][0] == '-' ) {
+ switch ( argv[1][1] ) {
+ case 'a': dumpInfo++; dumpColorMap++; dumpBits++; dumpHisto++; break;
+ case 'i': dumpInfo++; break;
+ case 'c': dumpColorMap++; break;
+ case 'b': dumpBits++; break;
+ case 'h': dumpHisto++; break;
+ case 'u': updateColorCount++; break;
+ case 'z': zeroColorCount++; break;
+ case 's': setColorCount++; break;
+ case 'f': fixColorMap++; break;
+ default:
+ fprintf( stderr, "bad option %s\n", argv[1] );
+ }
+ argc--;
+ argv++;
+ }
+ if ( argc > 2 && dumpInfo+dumpColorMap+dumpBits+dumpHisto > 0 )
+ namenames++;
+ while ( argc > 1 ) {
+ fixbmp( argv[1] );
+ argc--;
+ argv++;
+ }
+}
diff --git a/app/help/genhelp.c b/app/help/genhelp.c
new file mode 100644
index 0000000..7f79330
--- /dev/null
+++ b/app/help/genhelp.c
@@ -0,0 +1,212 @@
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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.
+ */
+//#ifdef WINDOWS
+#include <stdlib.h>
+//#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#define I18NHEADERFILE "i18n.h"
+
+typedef enum { MSWPOPUP, XVINFO, BALLOONHELP, HPJALIAS, ALIASREF, ALIASDEF, DEFINE, BALLOONHELPI18N } mode_e;
+
+void remap_minus( char * cp )
+{
+ for ( ; *cp; cp++ )
+ if ( *cp == '-' )
+ *cp = '_';
+}
+
+void process( mode_e mode, FILE * inFile, FILE * outFile )
+{
+ char line[256];
+ char * cp;
+ char * contents;
+ char * alias;
+ char * extHelp;
+ int lineNum;
+ int len;
+
+ switch ( mode ) {
+ case MSWPOPUP:
+ break;
+ case XVINFO:
+ break;
+ case BALLOONHELP:
+ case BALLOONHELPI18N:
+ fputs( "/*\n * DO NOT EDIT! This file has been automatically created by genhelp.\n * Changes to this file will be overwritten.\n */\n", outFile );
+ fprintf( outFile, "#include <stdio.h>\n" );
+ fprintf( outFile, "#include \"wlib.h\"\n" );
+ if( mode == BALLOONHELPI18N )
+ fprintf( outFile, "#include \"" I18NHEADERFILE "\"\n" );
+
+ fprintf( outFile, "wBalloonHelp_t balloonHelp[] = {\n\n" );
+ break;
+ case HPJALIAS:
+ fprintf( outFile, "[ALIAS]\r\n" );
+ break;
+ case ALIASREF:
+ break;
+ case ALIASDEF:
+ break;
+ case DEFINE:
+ break;
+ }
+
+ lineNum = 0;
+ while ( fgets( line, sizeof line, inFile ) != NULL ) {
+ lineNum++;
+ if (line[0] == '#')
+ continue;
+ len = (int)strlen( line );
+ if (line[len-1] == '\n' ) len--;
+ if (line[len-1] == '\r' ) len--;
+ line[len] = '\0';
+ if (len == 0)
+ continue;
+ contents = strchr( line, '\t' );
+ if (contents == NULL) {
+ fprintf( stderr, "Not tab on line %d\n%s\n", lineNum, line );
+ continue;
+ }
+ *contents++ = '\0';
+ alias = strchr( contents, '\t' );
+ if (alias != NULL) {
+ *alias++ = '\0';
+ extHelp = strchr( alias, '\t' );
+ if (extHelp != NULL) {
+ *extHelp++ = '\0';
+ }
+ }
+ switch ( mode ) {
+ case MSWPOPUP:
+ remap_minus( line );
+ remap_minus( contents );
+ fprintf( outFile, "\\page #{\\footnote _%s}\r\n", line );
+ for ( cp=contents; *cp; cp++ ) {
+ if ( (*cp) & 0x80 ) {
+ fprintf( outFile, "\\'%2.2X", (unsigned char)*cp );
+ } else {
+ fprintf( outFile, "%c", *cp );
+ }
+ }
+ fprintf( outFile, "\r\n" );
+ break;
+ case XVINFO:
+ if ( *contents )
+ fprintf( outFile, ":%s\n%s\n", line, contents );
+ break;
+ case BALLOONHELP:
+ case BALLOONHELPI18N:
+ if ( *contents )
+ if( mode == BALLOONHELP )
+ fprintf( outFile, "\t{ \"%s\", \"%s\" },\n", line, contents );
+ else
+ fprintf( outFile, "\t{ \"%s\", N_(\"%s\") },\n", line, contents );
+ else
+ fprintf( outFile, "\t{ \"%s\" },\n", line );
+ break;
+ case HPJALIAS:
+ if (alias && *alias) {
+ remap_minus( line );
+ remap_minus( alias );
+ fprintf( outFile, "%s=%s\r\n", line, alias );
+ }
+ break;
+ case ALIASREF:
+ if (alias && *alias)
+ fprintf( outFile, "%s\n", alias );
+ break;
+ case ALIASDEF:
+ if (alias && *alias)
+ fprintf( outFile, "%s\n", line );
+ break;
+ case DEFINE:
+ fprintf( outFile, "%s\n", line );
+ break;
+ }
+ }
+
+ switch ( mode ) {
+ case MSWPOPUP:
+ break;
+ case XVINFO:
+ fprintf( outFile, ":\n" );
+ break;
+ case BALLOONHELP:
+ case BALLOONHELPI18N:
+ fprintf( outFile, "\n { NULL, NULL } };\n" );
+ break;
+ case HPJALIAS:
+ break;
+ case ALIASREF:
+ break;
+ case ALIASDEF:
+ break;
+ case DEFINE:
+ break;
+ }
+
+}
+
+
+int main ( int argc, char * argv[] )
+{
+ FILE * inFile, * outFile;
+ mode_e mode;
+ if ( argc != 4 ) {
+ fprintf( stderr, "Usage: %s (-msw|-xv|-bh|-hpj|-ref) INFILE OUTFILE\n", argv[0] );
+ exit(1);
+ }
+ if ( strcmp( argv[1], "-msw" ) == 0 )
+ mode = MSWPOPUP;
+ else if ( strcmp( argv[1], "-xv" ) == 0 )
+ mode = XVINFO;
+ else if ( strcmp( argv[1], "-bh" ) == 0 )
+ mode = BALLOONHELP;
+ else if ( strcmp( argv[1], "-bhi" ) == 0 )
+ mode = BALLOONHELPI18N;
+ else if ( strcmp( argv[1], "-hpj" ) == 0 )
+ mode = HPJALIAS;
+ else if ( strcmp( argv[1], "-aliasref" ) == 0 )
+ mode = ALIASREF;
+ else if ( strcmp( argv[1], "-aliasdef" ) == 0 )
+ mode = ALIASDEF;
+ else if ( strcmp( argv[1], "-define" ) == 0 )
+ mode = DEFINE;
+ else {
+ fprintf( stderr, "Bad mode: %s\n", argv[1] );
+ exit(1);
+ }
+
+ inFile = fopen( argv[2], "r" );
+ if (inFile == NULL) {
+ perror( argv[2] );
+ exit(1);
+ }
+ outFile = fopen( argv[3], "w" );
+ if (outFile == NULL) {
+ perror( argv[3] );
+ exit(1);
+ }
+
+ process( mode, inFile, outFile );
+ exit(0);
+}
diff --git a/app/help/genhelp.in b/app/help/genhelp.in
new file mode 100644
index 0000000..b15a727
--- /dev/null
+++ b/app/help/genhelp.in
@@ -0,0 +1,705 @@
+Help Invokes on-line help for this dialog
+cancel Cancels this command
+Close Closes the dialog
+#
+cmdAbout About box dialog
+cmdAbove Move Selected object to top
+cmdAddElevations Raise or Lower all Selected tracks
+cmdBelow Move Selected object to bottom
+cmdBlockCreate Create Block
+cmdBlockDelete Delete Block
+cmdBlockEdit Edit Block
+cmdBlockSetCmd Block
+cmdCarDesc Create a new Car/Loco description
+cmdCarInventory Manage your Car and Loco Inventory
+cmdCircleCenter Create track circle from center cmdCircle
+cmdCircleFixedRadius Create fixed radius track circle cmdCircle
+#cmdCircleMode Default Circle creation mode cmdCircle
+cmdCircleSetCmd Set Circle Track creation mode cmdCircle
+cmdCircleTangent Create track circle from tangent cmdCircle
+cmdClearElevations Removes elevation from Selected tracks
+cmdCmdopt Command Options dialog
+cmdColor Controls colors
+cmdConnect Connect two tracks
+cmdCopy Copy selected objects to clipboard
+cmdCurveCenter Create curved track from center cmdCurve
+cmdCurveChord Create curved track from chord cmdCurve
+cmdCurveEndPt Create curved track from end-point cmdCurve
+cmdCurveSetCmd Set Curve Track creation mode cmdCurve
+cmdCurveTangent Create curved track from tangent cmdCurve
+cmdCustmgm Manipulate Custom designer entries
+cmdCut Moves selected objects to clipboard
+cmdDelete Delete objects
+cmdDemo Playback demos
+cmdDescribe Describe objects
+cmdDeselectAll Deselect all selected objects cmdSelect
+cmdDisplay Change Display parameters
+cmdDrawBench Create benchwork cmdDraw
+cmdDrawBox Create a box cmdDraw
+cmdDrawCircleSetCmd Set Circle drawing command cmdDraw
+cmdDrawCircle Create a circle cmdDraw
+cmdDrawCircleCenter Draw a circle line from center cmdDraw
+cmdDrawCircleFixedRadius Draw a fixed radius circle line cmdDraw
+cmdDrawCircleTangent Draw a circle line from tangent cmdDraw
+cmdDrawCurveSetCmd Set Curve drawing command cmdDraw
+cmdDrawCurve Create a curved line cmdDraw
+cmdDrawCurveEndPt Create a curved line from End cmdDraw
+cmdDrawCurveCenter Create a curved line from center cmdDraw
+cmdDrawCurveChord Create a curved line from chord cmdDraw
+cmdDrawCurveTangent Create a curved line from tangent cmdDraw
+cmdDrawDimLine Create a dimension line cmdDraw
+cmdDrawFilledBox Create a filled box cmdDraw
+cmdDrawFilledCurve Create a filled circle cmdDraw
+cmdDrawFilledCircleCenter Draw a filled circle from center cmdDraw
+cmdDrawFilledCircleFixedRadius Draw a fixed radius filled circle cmdDraw
+cmdDrawFilledCircleTangent Draw a filled circle from tangent cmdDraw
+cmdDrawPolygon Create a filled polygon cmdDraw
+cmdDrawPolyline Create a polyline cmdDraw
+cmdDrawLine Create a straight line cmdDraw
+cmdDrawLineSetCmd Set Line drawing command cmdDraw
+cmdDrawShapeSetCmd Set Shape drawing command cmdDraw
+cmdDrawTableEdge Draw table edge cmdDraw
+cmdEasement Easement menu
+cmdElevation Change Elevations
+cmdEnumerate Generate a Parts List of selected objects
+cmdExport Export a .xti file
+cmdExportDXF Export a DXF file
+cmdFileNote General note about the layout
+cmdFlip Flip selected objects
+cmdGrid Adjust snap grid
+cmdGridEnable Enable snap grid cmdGrid
+cmdGridShow Show snap grid cmdGrid
+cmdGroup Create a structure from a Group of objects
+cmdHandLaidTurnout Create a hand-laid turnout
+cmdHelix Create a track helix
+#cmdHotBar Place a turnout or structure
+cmdImport Import a .xti file cmdExport
+cmdJoin Join two tracks
+cmdLayer Change Layers
+cmdLayerSet Selects the current drawing layer cmdLayer
+#cmdLayerShow0 Shows or hides layers cmdLayer
+#cmdLayerShow1 Shows or hides layers cmdLayer
+#cmdLayerShow10 Shows or hides layers cmdLayer
+#cmdLayerShow11 Shows or hides layers cmdLayer
+#cmdLayerShow12 Shows or hides layers cmdLayer
+#cmdLayerShow13 Shows or hides layers cmdLayer
+#cmdLayerShow14 Shows or hides layers cmdLayer
+#cmdLayerShow15 Shows or hides layers cmdLayer
+#cmdLayerShow16 Shows or hides layers cmdLayer
+#cmdLayerShow17 Shows or hides layers cmdLayer
+#cmdLayerShow18 Shows or hides layers cmdLayer
+#cmdLayerShow19 Shows or hides layers cmdLayer
+#cmdLayerShow2 Shows or hides layers cmdLayer
+#cmdLayerShow3 Shows or hides layers cmdLayer
+#cmdLayerShow4 Shows or hides layers cmdLayer
+#cmdLayerShow5 Shows or hides layers cmdLayer
+#cmdLayerShow6 Shows or hides layers cmdLayer
+#cmdLayerShow7 Shows or hides layers cmdLayer
+#cmdLayerShow8 Shows or hides layers cmdLayer
+#cmdLayerShow9 Shows or hides layers cmdLayer
+cmdLayout Layout parameters
+#cmdLoosen Disconnect tracks at loose joints nohelp
+cmdModify Modify or extend a track
+cmdMove Move selected objects
+cmdMoveLabel Move a label
+cmdMoveToCurrentLayer Move selected objects to current layer
+cmdNote Place a note on the layout
+cmdOutputbitmap Print a BitMap
+cmdParallel Create a parallel track
+cmdParameter Register register
+cmdPaste Copy objects from clipboard
+cmdPref Perferences dialog
+cmdPricelist Display prices of turnouts, sectional tracks and structures
+cmdPrint Print the layout
+cmdPrmfile Loads and unloads parameter files
+cmdProfile Elevation Profile Command
+cmdProfileDraw Profile cmdProfile
+cmdRecord Command recorder
+cmdRedo Redo last undo
+cmdRefreshCompound Update selected Turnout and Structure definitions
+cmdRescale Rescale selected objects
+cmdRotate Rotate selected object(s)
+cmdRuler Show a ruler
+cmdSelect Select objects
+cmdSelectAll Selects all objects on the layout cmdSelect
+cmdSelectCurrentLayer Selects all objects in the current Layer layer
+cmdSelectInvert Invert current selection
+cmdSplitTrack Split a track
+cmdSelectOrphaned Select stranded (unconnected) track pieces
+cmdSticky Choose which commands are sticky
+cmdStraight Create straight track
+cmdStructure Place a structure on the layout
+cmdSwitchMotorCreate Create Switch Motor
+cmdSwitchMotorDelete Delete Switch Motor
+cmdSwitchMotorEdit Edit Switch Motor
+cmdSwitchMotorSetCmd Switch Motors
+cmdText Enter text on the layout
+cmdTextSize Controls the size of the entered text cmdText
+#cmdTighten Remove slack from connected tracks
+cmdTip Tip of the Day window
+cmdTrain Run Trains
+cmdTrainPause Pause/Resume Trains cmdTrain
+cmdTrainNewCar Place a car on the layout cmdTrain
+cmdTrainExit Exit Trains cmdTrain
+cmdTunnel Hide/Unhide a track
+cmdTurnout Place a turnout or sectional track
+cmdTurnoutNew Create a new turnout definition
+cmdTurntable Place a turntable
+cmdUpdatetitle Updates old source files with 3 part titles
+cmdUndo Undo last command
+cmdUngroup Ungroup objects
+cmdWidth0 Draw tracks with thin lines editM
+cmdWidth2 Draw tracks with medium lines editM
+cmdWidth3 Draw tracks with thick lines editM
+cmdZoom Change drawing scale editZoom
+cmdZoomIn Zoom in editZoomIn
+cmdZoomOut Zoom out editZoomOut
+#
+#
+menuFile File Menu
+menuFile-save Save layout
+menuFile-saveAs Save layout under a new name
+menuFile-clear New layout
+menuFile-enum Generate parts list
+menuFile-load Load a layout
+menuFile-quit Exit the program
+menuFile-revert Revert to last saved state of layout plan
+#
+editM Edit menu
+menuEdit-redraw Redraw layout
+menuEdit-zoomIn Zoom in
+menuEdit-zoomOut Zoom out
+#
+toolsM Tools menu
+#
+menuView View menu
+menuToolbar Toolbar configuration
+#
+menuTools Tools menu
+#
+menuOption Options menu
+#
+menuMacro Playback/Record commands
+#
+menuWindow Window menu
+#
+menuHelp Help menu
+menuHelpRecentMessages Recent error messages and explanations menuHelp
+#
+#
+hotBarLeft Move Hot Bar left cmdHotBar
+hotBarRight Move Hot Bar right cmdHotBar
+infoBarCount Total track count statusBar
+infoBarPosX X Position of cursor statusBar
+infoBarPosY Y Position of cursor statusBar
+infoBarScale Drawing scale statusBar
+infoBarStatus Message and status line statusBar
+main-draw Main layout canvas
+mainDraw Main layout canvas
+main-canvas Main drawing canvas
+main-commandbar Command buttons
+main-menubar Menus
+main-titlebar Tile, Filename and Window Manager buttons
+main-hotbar Turnout and Structure Hot Bar
+main-layers Active layer list and layer buttons
+map-draw Map window
+map-hilight This is the portion of the layout shown in the Main Window canvas
+#
+#
+addElev-value Raise or Lower all Selected Track cmdAddElevations
+#
+carpart-ok Add or Update car object cmdCarInventory
+carpart-manuf Manufacturer name cmdCarInventory
+carpart-prototype Car Prototype cmdCarInventory
+carpart-prototype-list Car Prototype cmdCarInventory
+carpart-isLoco Is the Car a Locomotive? cmdCarInventory
+carpart-partno-list Part Number and Description cmdCarInventory
+carpart-partno Manufacturer Part Number cmdCarInventory
+carpart-import Use the Selected figure as the car image cmdCarInventory
+carpart-reset Use the default figure as the car image cmdCarInventory
+carpart-desc Optional description of the Car Part cmdCarInventory
+carpart-flip Flip car image cmdCarInventory
+carpart-dispmode Display Car Item information or reporting marks and dimensions cmdCarInventory
+carpart-road Full Roadname cmdCarInventory
+carpart-type Car Type cmdCarInventory
+carpart-protokind-list Car Type cmdCarInventory
+carpart-repmark Reporting Marks (Roadname abbreviation) cmdCarInventory
+carpart-number Car Number cmdCarInventory
+carpart-bodyColor Car body Color cmdCarInventory
+carpart-carLength Length of car body cmdCarInventory
+carpart-carWidth Width of car body cmdCarInventory
+carpart-trkCenter Distance between Trucks cmdCarInventory
+carpart-cplrMount Coupler are mounted on body or truck cmdCarInventory
+carpart-cpldLen Overall Coupled Length cmdCarInventory
+carpart-cplrLen Coupler Length from end of car cmdCarInventory
+carpart-canvas Diagram of Car cmdCarInventory
+carpart-index Item Index Number cmdCarInventory
+carpart-purchPrice Original Purchase Price cmdCarInventory
+carpart-currPrice Current Price cmdCarInventory
+carpart-condition Condition of car cmdCarInventory
+carpart-purchDate Original Purchase Date cmdCarInventory
+carpart-serviceDate Last Service Date cmdCarInventory
+carpart-quantity Number of identical cars to be entered cmdCarInventory
+carpart-multinum Do all the cars have the same Number? cmdCarInventory
+carpart-notes Notes about the car cmdCarInventory
+carpart-new Create a new car Part or Prototype definitions cmdCarInventory
+carpart-new-menu Create a new car Part or Prototype definitions cmdCarInventory
+
+#
+carinv-ok Finds the selected Car Item on the layout cmdCarInvertory
+carinv-sort1 Sort the Item list cmdCarInvertory
+carinv-sort2 Sort the Item list cmdCarInvertory
+carinv-sort3 Sort the Item list cmdCarInvertory
+carinv-sort4 Sort the Item list cmdCarInvertory
+carinv-list cmdCarInvertory
+carinv-edit Edit the selected Car Item cmdCarInvertory
+carinv-add Add a new Car Item cmdCarInvertory
+carinv-delete Delete the selected Car Items cmdCarInvertory
+carinv-import Import a Car Item .csv file cmdCarInvertory
+carinv-export Export a Car Item .csv file cmdCarInvertory
+carinv-savetext Create a text list of the Car Items cmdCarInvertory
+#
+circle-radius Specifies the radius of the circle track cmdCircle
+#
+cmdopt-move-quick How to draw track being moved/rotated cmdCmdopt
+cmdopt-preselect Default command is Describe or Select cmdCmdopt
+cmdopt-rightclickmode Action to invoke on Right-Click cmdCmdopt
+cmdopt-ok cmdCmdopt
+#
+contents-label Contents Label for new Parameter file cmdCustmgm
+#
+custmgm-inx List of custom designed turnouts and structures cmdCustmgm
+custmgm-edit Invoke designer editor cmdCustmgm
+custmgm-delete Remove selected entries cmdCustmgm
+custmgm-export Copy selected entries to Parameter File cmdCustmgm
+custmgm-new Create a New part or prototype cmdCustmgm
+custmgm-ok Update custom file and close cmdCustmgm
+#
+demo-step Executes the next step of the demo cmdDemo
+demo-next Skip to next demo cmdDemo
+demo-quit Stops the demonstration and returns you to XTrackCAD cmdDemo
+demo-speed Select speed of Playback cmdDemo
+demo-text This is where comments about the demo are displayed cmdDemo
+#
+describe-F1
+describe-F2
+describe-F3
+describe-F4
+describe-F5
+describe-F6
+describe-F7
+describe-F8
+describe-F9
+describe-F10
+describe-F11
+describe-F12
+describe-F13
+describe-F14
+describe-F15
+describe-F16
+describe-F17
+describe-F18
+describe-F19
+describe-F20
+describe-I1
+describe-I2
+describe-I3
+describe-I4
+describe-I5
+describe-S1
+describe-S2
+describe-S3
+describe-Y1
+describe-C1
+describe-L1
+describe-L2
+describe-LE1
+describe-T1
+describe-P1
+#
+display-autoPan Move the Main canvas if you drag near the edge cmdDisplay
+display-color-layers Color tracks or other objects by layer
+display-tunnels Controls the drawing of hidden tracks cmdDisplay
+display-endpt Controls the drawing of End-Points cmdDisplay
+display-tiedraw How to draw track ties cmdDisplay
+display-centerdraw Show crosshair at center of curves cmdDisplay
+display-tworailscale Drawing scale when to draw tracks with 2 rails cmdDisplay
+display-mapscale Drawing scale of the map window cmdDisplay
+display-livemap Whether the main layout is updated while dragging on the Map cmdDisplay
+display-labelenable Enable labels for Turnouts, Flextrack Lengths and Elevations cmdDisplay
+display-labelscale When to label Turnout, Flextrack Lengths and Elevations cmdDisplay
+display-description-fontsize Font size for labels on layout cmdDisplay
+display-hotbarlabels Label elements on the Hot Bar cmdDisplay
+display-layoutlabels Label elements on layout cmdDisplay
+display-listlabels Label elements for lists cmdDisplay
+display-carhotbarlabels How to group cars on the Train Hot Bar cmdDisplay
+display-trainpause Delay (in mS) between updating train movements cmdDisplay
+display-hideTrainsInTunnels Don't show trains in tunnels when tunnels are hidden cmdDisplay
+#display-ok Update the display cmdDisplay
+display-ok cmdDisplay
+#
+draw-linewidth Width of the lines cmdDraw
+draw-linecolor Color of the lines cmdDraw
+draw-benchlist List of types of Lumber cmdDraw
+draw-benchcolor Color of Benchwork cmdDraw
+draw-benchorient Orientation of Benchwork cmdDraw
+draw-arrowsize Size of Dimension Arrows cmdDraw
+#
+easement-val This controls the sharpness of the easement curve cmdEasement
+easement-r Minumum radius cmdEasement
+easement-x Maximum offset cmdEasement
+easement-l Easement length cmdEasement
+easement-radio These radio buttons are a short-cut for Values of 0.0, 0.5, 1.0 and 2.0. None turns Easements off cmdEasement
+easement-ok Complete easement selection cmdEasement
+#
+elev-mode Type of elevation cmdElevation
+elev-value Height of End Point cmdElevation
+elev-computed Compute elevation based on neighbors cmdElevation
+elev-grade Compute grade based on neighbors cmdElevation
+elev-station Specify a name for an End-Point cmdElevation
+elev-ok cmdElevation
+#
+enum-print Print parts list cmdEnumerate
+enum-printsetup Invoke the Print Setup dialog printSetup
+enum-save Save parts list to file cmdEnumerate
+enum-text This is the list of parts for the layout cmdEnumerate
+enum-list-prices Enable prices on the Parts List cmdEnumerate
+#
+grid-horzspacing Spacing between major grid lines cmdGrid
+grid-horzdivision Allows the spacing to be subdivided cmdGrid
+grid-horzenable Specifies if positions are snaped in this direction cmdGrid
+grid-vertspacing Spacing between major grid lines cmdGrid
+grid-vertdivision Allows the spacing to be subdivided cmdGrid
+grid-vertenable Specifies if positions are snaped in this direction cmdGrid
+grid-origx Shows the origin and angle of the grid cmdGrid
+grid-origy Shows the origin and angle of the grid cmdGrid
+grid-origa Shows the origin and angle of the grid cmdGrid
+grid-show Specifies if the grid is shown cmdGrid
+grid-ok Completes the grid specification cmdGrid
+#
+group-manuf Manufacturer cmdGroup
+group-desc Description cmdGroup
+group-partno Part Number cmdGroup
+group-segcnt Number of segments in Group cmdGroup
+group-replace Replace the Selected object with the new definition? cmdGroup
+group-ok Creates a new Structure (or Turnout) cmdGroup
+#
+helix-elev Elevation difference of Helix End-Points cmdHelix
+helix-radius Helix Radius cmdHelix
+helix-turns Number of turns in the helix cmdHelix
+helix-angSep Angle betweek helix entrance and exit cmdHelix
+helix-grade Grade in helix cmdHelix
+helix-vertSep Separation between helix layers cmdHelix
+#
+layer-layer Layer list cmdLayer
+layer-name Layer Name cmdLayer
+layer-color Color of layer cmdLayer
+layer-visible Layer is drawn on Main window cmdLayer
+layer-frozen Layer cannot be changed cmdLayer
+layer-onmap Layer is drawn on Map window cmdLayer
+layer-button-count Number of layer buttons to show cmdLayer
+layer-object-count Number of objects in this layer cmdLayer
+layer-ok cmdLayer
+layer-reset Load layer configuration from default cmdLayer
+layer-save Save current layer configuration as default cmdLayer
+layer-clear Overwrite layer configuration with system default values cmdLayer
+#
+layout-roomsizeX Specifies the size of the room (in inches or centimeters) cmdLayout
+layout-roomsizeY Specifies the size of the room (in inches or centimeters) cmdLayout
+layout-title1 Specifies the layout Title that will appear on printouts cmdLayout
+layout-title2 Specifies the layout Subtitle that will appear on printouts cmdLayout
+layout-scale Specifies the Modelling Scale cmdLayout
+layout-gauge Specifies the rail gauge, ie. the distance between the rails cmdLayout
+layout-mintrackradius Specifies minimum track radius (in inches or centimeters). Tracks with a smaller radius are considered exceptional. cmdLayout
+layout-maxtrackgrade Specifies maximum track elevation expressed as a percent (%). Tracks with a larger elevation are considered exceptional. cmdLayout
+#
+newcar-road Roadname cmdTrain
+newcar-number Car Number cmdTrain
+#
+note-text This is the body of the Note. To change this select Modify from the File Menu cmdNote
+note-ok cmdNote
+#
+outputbitmap-density Specifies number of pixels per inch (or centimeter) cmdOutputbitmap
+outputbitmap-ok cmdOutputbitmap
+outputbitmap-toggles Specifies whether Layout Titles, Borders or Track Centerlines are printed on the BitMap cmdOutputbitmap
+#
+parallel-separation Specifies the separation between parallel tracks cmdParallel
+#
+parameter-name Enter your name as specified in the XTrackCAD Registration Notice register
+parameter-key Enter the key value as specified in the XTrackCAD Registration Notice register
+parameter-ok Validates the name and key. Terminates the registration command register
+#
+pref-anglesystem 0° is up or to the right cmdPref
+pref-units Choose english (inches) or metric (centimeters) cmdPref
+pref-dstfmt How to display length measurements cmdPref
+pref-minlength Do not create tracks to be shorter than this value cmdPref
+pref-connectdistance Maximum distance between connected end points cmdPref
+pref-connectangle Minimum angle between connected End-Points cmdPref
+pref-turntable-angle Specifies the minimum angle between tracks connected to a turntable cmdPref
+pref-coupling-speed-max Trains will crash above this speed cmdPref
+pref-balloonhelp Enable/Disable balloon popup help windows cmdPref
+pref-dragpixels How far you can move the mouse before its considered a drag cmdPref
+pref-dragtimeout How long you can hold a mouse button down before its considered a drag cmdPref
+pref-mingridspacing Minimum distance (in pixels) between grid lines/ticks cmdPref
+pref-checkpoint Specifies the Check Point frequency; number of modifications made since the last save. cmdPref
+pref-onstartup Resume work on last layout or start with new layout cmdPref
+pref-ok cmdPref
+#
+pricelist-cost Updated cost of current selected item cmdPricelist
+pricelist-entry Item cmdPricelist
+pricelist-inx Selection list for prices cmdPricelist
+pricelist-flexlen Price of specified length of flex-track cmdPricelist
+pricelist-flexunit Price of specified length of flex-track cmdPricelist
+pricelist-flexcost Price of specified length of flex-track cmdPricelist
+pricelist-ok cmdPricelist
+#
+print-scale Controls the reduction (scale) of the printout cmdPrint
+print-pagew Scaled page width (Scale times physical page width) cmdPrint
+print-max Sets page size to the maximum (based on scale and physical page size) cmdPrint
+print-pageh Scaled page height (Scale times physical page height) cmdPrint
+print-snapshot Sets scale, origin and angle for a one page printout of the layout cmdPrint
+print-format Print page in Portrait or Landscape format cmdPrint
+print-order Order of printing pages cmdPrint
+print-style Print Title, Date, Author and other information at bottom of page? cmdPrint
+print-physsize Ignore unprintable page margins? cmdPrint
+print-registrationMarks Print Registration Marks at 1:1? cmdPrint
+print-grid Print Snap Grid? cmdPrint
+print-ruler Print Rulers on all page edges? cmdPrint
+print-roadbed Print Roadbed Outline? cmdPrint
+print-roadbedWidth Print Roadbed Outline cmdPrint
+print-origx Origin of the print grid. This is useful if you want to reprint a set of pages cmdPrint
+print-origy Origin of the print grid. This is useful if you want to reprint a set of pages cmdPrint
+print-reset Resets the origin and angle to 0 cmdPrint
+print-origa Origin of the print grid. This is useful if you want to reprint a set of pages cmdPrint
+print-clear Deselects all pages cmdPrint
+print-setup Invoke the Print Setup dialog printSetup
+print-ok Print selected pages and terminates the print command cmdPrint
+#
+prmfile-inx List of loaded and unloaded parameter files cmdPrmfile
+prmfile-mode Show parameter files by names or descriptions cmdPrmfile
+prmfile-action Toggle the loaded status of the selected parameter file cmdPrmfile
+prmfile-browse Find a parameter file for loading cmdPrmfile
+prmfile-ok Update parameter file list cmdPrmfile
+#
+profile-canvas Profile of specified path cmdProfile
+profile-clear Clear the profile cmdProfile
+profile-print Print the profile cmdProfile
+profile-ok cmdProfile
+#
+record-stop Stop recording cmdRecord
+record-message Insert a message cmdRecord
+record-end End a message cmdRecord
+record-text Message body cmdRecord
+#
+refreshSpecial-list Possible turnouts cmdRefreshSpecial
+refreshSpecial-skip Skip this turnout cmdRefreshSpecial
+refreshSpecial-ok cmdRefreshSpecial
+#
+rename-manuf Manufacturer of Object cmdCustmgm
+rename-desc Description of Object cmdCustmgm
+rename-partno Part Nuber of Object cmdCustmgm
+rename-ok cmdCustmgm
+#
+rescale-toggle Rescale by Scale Conversion or by Ratio cmdRescale
+rescale-fromS Original Scale of the selected objects cmdRescale
+rescale-fromG Original Gauge of the selected objects cmdRescale
+rescale-toS New Scale of the selected objects cmdRescale
+rescale-toG New Gauge of the selected objects cmdRescale
+rescale-change-dim Change track dimensions to new scale cmdRescale
+rescale-ratio Change size by this amount cmdRescale
+rescale-ok cmdRescale
+#
+rgbcolor-snapgrid Snap Grid Line and Division cmdRgbcolor
+rgbcolor-marker X and Y position markers cmdRgbcolor
+rgbcolor-border Border rulers, room boundaries and table edges cmdRgbcolor
+rgbcolor-crossmajor Primary Axis of grid rotation cmdRgbcolor
+rgbcolor-crossminor Secondary Axis of grid rotation cmdRgbcolor
+rgbcolor-normal Unselected tracks cmdRgbcolor
+rgbcolor-selected Selected tracks cmdRgbcolor
+rgbcolor-profile Color of tracks on the Profile path cmdRgbcolor
+rgbcolor-exception Color of Exceptional tracks cmdRgbcolor
+rgbcolor-tie Color of track ties cmdRgbcolor
+rgbcolor-ok Updates the colors cmdRgbcolor
+#
+rotate-rotate Angle in degrees cmdRotate
+rotate-ok Rotate object(s) by specified amount cmdRotate
+#
+sticky-set Choose commands to be sticky cmdSticky
+sticky-ok Make the commands sticky cmdSticky
+#
+structure-list List of available structure cmdStructure
+structure-canvas Diagram of the selected structure cmdStructure
+structure-hide Hide Selection window when placing Structure cmdStructure
+structure-stats Drawing scale and size cmdStructure
+structure-ok Complete structure placement cmdStructure
+#
+structure-pier-inx Choose a Pier number cmdStructure
+#
+text-fontsize Controls the size of the entered text cmdText
+#
+tip-text Useful information about the program cmdTip
+tip-showatstart Show Tip of the Day every time the program starts cmdTip
+tip-next Show the next Tip of the Day cmdTip
+tip-prev Show the previous Tip of the Day cmdTip
+tip-ok cmdTip
+#
+toolbarM Controls which Command Buttons are displayed
+#
+train-newcar-index List of Cars cmdTrain
+train-list List of active trains cmdTrain
+train-speed Speed cmdTrain
+train-distance Train odometer cmdTrain
+train-zeroDistance Reset odometer to 0 cmdTrain
+train-goto Find train on layout cmdTrain
+train-follow Follow train around layout cmdTrain
+train-autoreverse Flip direction at End Of Track cmdTrain
+train-direction Change direction of train cmdTrain
+train-stop Stop the train cmdTrain
+#
+turnout-list List of available turnouts for the current scale cmdTurnout
+turnout-canvas Diagram of the currently selected turnout. Click on a End-Point to select the Active End-Point cmdTurnout
+turnout-new A menu list of various type of turnouts and sectional tracks you can define
+turnout-hide Hide Selection window when placing Turnout cmdTurnout
+turnout-activeEndPoint The selected Active End-Point cmdTurnout
+turnout-current Current selected turnout, (displayed in the diagram window) cmdTurnout
+turnout-endPoint One the End-Points that can be selected cmdTurnout
+turnout-ok cmdTurnout
+#
+turnoutNew-angle1 Angle of the specified track to the center line of the turnout
+turnoutNew-angle2 Angle of the specified track to the center line of the turnout
+turnoutNew-angleMode Specifies if angles are entered as Frog Numbers or in degrees cmdTurnoutNew
+turnoutNew-desc1 Desciption
+turnoutNew-desc2 Desciption
+turnoutNew-label Turnout description (Manuf., Size, Part Number, etc) cmdTurnoutNew
+turnoutNew-len0 Length from the base to the end of the specified track
+turnoutNew-len1 Length from the base to the end of the specified track
+turnoutNew-len2 Length from the base to the end of the specified track
+turnoutNew-manuf Manufacturer
+turnoutNew-off1 Offset of the track End-Point from the center line of the turnout
+turnoutNew-off2 Offset of the track End-Point from the center line of the turnout
+turnoutNew-partno1 Part Number
+turnoutNew-partno2 Part Number
+turnoutNew-print Prints a full size diagram of the turnout for checking cmdTurnoutNew
+turnoutNew-ok Prints a full size diagram of the turnout for checking cmdTurnoutNew
+turnoutNew-color Color of Roadbed lines cmdTurnoutNew
+turnoutNew-roadbedLineWidth Width of Roadbed lines cmdTurnoutNew
+turnoutNew-roadbedWidth Width of Roadbed cmdTurnoutNew
+turnoutNew-printsetup Invoke the Print Setup dialog printSetup
+turnoutNew-done Closes the window and returns to the Turnout Selection window cmdTurnoutNew
+#
+turntable-diameter Specifies the diameter of the turntable cmdTurntable
+#
+updatetitle-old Old Turnout title cmdUpdatetitle
+updatetitle-sel List of available titles cmdUpdatetitle
+updatetitle-ignore Leave the Turnouts' title unchanged cmdUpdatetitle
+updatetitle-load Invoke the Parameter Files dialog cmdUpdatetitle
+updatetitle-list List of available turnouts cmdUpdatetitle
+updatetitle-ok Update the Turnouts' title cmdUpdatetitle
+#
+#
+fontSelCancel Cancel fontSelW
+fontSelList List fontSelW
+fontSelOk Ok fontSelW
+fontSelSample Sample fontSelW
+fontSelSize Size fontSelW
+fontSelSlant Slant fontSelW
+fontSelW Font selection dialog
+fontSelWeight Weight fontSelW
+#
+printAbortW Printer Abort Window
+printFileName Print to filename
+printFontAlias Specify Postscript font alias mapping
+printSetup Displays the Print Setup window to change printers, orientation, paper size, etc.
+printSetupCancel Closes this dialog printSetup
+printSetupFormat Page orientation printSetup
+printSetupMargin Unprintable margins printSetup
+printSetupOk Updates and closes this dialog printSetup
+printSetupPaper Choose paper size printSetup
+printSetupPrinter Choose printer printSetup
+printSetupTest Print test page printSetup
+#
+#
+about No Help nohelp
+about-about No Help nohelp
+about-ok nohelp
+cmdDebug No Help nohelp
+loosen No Help nohelp
+misc-cur-turnout-ep
+misc-toolbarset No Help nohelp
+misc-showlayout No Help nohelp
+misc-showdisplay No Help nohelp
+misc-showcmdopt No Help nohelp
+misc-showeasement No Help nohelp
+misc-showfontSel No Help nohelp
+misc-showgrid No Help nohelp
+misc-showdebug No Help nohelp
+misc-sticky No Help nohelp
+misc-showpref No Help nohelp
+misc-showcolor No Help nohelp
+misc-showfileClear No Help nohelp
+misc-showparamFile No Help nohelp
+misc-showpriceList No Help nohelp
+misc-showprint No Help nohelp
+misc-showprintSetup No Help nohelp
+misc-showprintBitmap No Help nohelp
+misc-showpartsList No Help nohelp
+misc-shownotes No Help nohelp
+misc-showundo No Help nohelp
+misc-showredo No Help nohelp
+misc-showcut No Help nohelp
+misc-showcopy No Help nohelp
+misc-showpaste No Help nohelp
+misc-showdelete No Help nohelp
+misc-showtunnel No Help nohelp
+misc-showabove No Help nohelp
+misc-showbelow No Help nohelp
+misc-showwidth0 No Help nohelp
+misc-showwidth2 No Help nohelp
+misc-showwidth3 No Help nohelp
+misc-showrecompelev No Help nohelp
+misc-showcardesc No Help nohelp
+misc-showcaradd No Help nohelp
+misc-showselectAll No Help nohelp
+misc-showimport No Help nohelp
+misc-showexport No Help nohelp
+misc-showexportDXF No Help nohelp
+misc-showloosen No Help nohelp
+misc-group-objects No Help nohelp
+misc-ungroup-objects No Help nohelp
+misc-showcustomMgm No Help nohelp
+misc-showlayers No Help nohelp
+misc-showmoveToCurrentLayer No Help nohelp
+misc-showselectCurrentLayer No Help nohelp
+misc-showclearElevations No Help nohelp
+misc-showaddElevations No Help nohelp
+debug-Track No Help nohelp
+debug-EndPt No Help nohelp
+debug-ReadTracks No Help nohelp
+debug-Curve No Help nohelp
+debug-Join No Help nohelp
+debug-Turnout No Help nohelp
+debug-Structure No Help nohelp
+debug-Print No Help nohelp
+debug-ok nohelp
+map-canvas No Help nohelp
+#
+cmdLayerShow0 Layer cmdLayer
+cmdLayerShow1 Layer cmdLayer
+cmdLayerShow2 Layer cmdLayer
+cmdLayerShow3 Layer cmdLayer
+cmdLayerShow4 Layer cmdLayer
+cmdLayerShow5 Layer cmdLayer
+cmdLayerShow6 Layer cmdLayer
+cmdLayerShow7 Layer cmdLayer
+cmdLayerShow8 Layer cmdLayer
+cmdLayerShow9 Layer cmdLayer
+cmdLayerShow10 Layer cmdLayer
+cmdLayerShow11 Layer cmdLayer
+cmdLayerShow12 Layer cmdLayer
+cmdLayerShow13 Layer cmdLayer
+cmdLayerShow14 Layer cmdLayer
+cmdLayerShow15 Layer cmdLayer
+cmdLayerShow16 Layer cmdLayer
+cmdLayerShow17 Layer cmdLayer
+cmdLayerShow18 Layer cmdLayer
+cmdLayerShow19 Layer cmdLayer
diff --git a/app/help/genmessages.c b/app/help/genmessages.c
new file mode 100644
index 0000000..349e81e
--- /dev/null
+++ b/app/help/genmessages.c
@@ -0,0 +1,339 @@
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ * 2007 Martin Fischer
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef WINDOWS
+ #if _MSC_VER >=1400
+ #define strdup _strdup
+ #endif
+#endif
+
+#define I18NHEADERFILE "i18n.h"
+
+typedef struct helpMsg_t * helpMsg_p;
+typedef struct helpMsg_t {
+ char * key;
+ char * title;
+ char * help;
+ } helpMsg_t;
+
+helpMsg_t helpMsgs[200];
+int helpMsgCnt = 0;
+
+struct transTbl {
+ char *inChar;
+ char *outChar[];
+};
+
+/* ATTENTION: make sure that the characters are in the same order as the equivalent escape sequences below */
+
+/* translation table for unicode sequences understood by Halibut */
+struct transTbl toUnicode = {
+ "\xB0\0",
+ { "\\u00B0",
+ "\\0" }
+};
+
+/* translation table for escape sequences understood by C compiler */
+
+struct transTbl toC = {
+ "\n\\\"\0",
+ { "\\n",
+ "\\\\",
+ "\\\"",
+ "\\0" }
+};
+
+
+char *
+TranslateString( char *srcString, struct transTbl *trTbl )
+{
+ char *destString;
+ char *cp;
+ char *cp2;
+ size_t bufLen = strlen( srcString ) + 1;
+ char *idx;
+
+ /* calculate the expected result length */
+ for( cp = srcString; *cp; cp++ )
+ if( idx = strchr( trTbl->inChar, *cp )) /* does character need translation ? */
+ bufLen += strlen( (trTbl->outChar)[idx - trTbl->inChar ] ) - 1; /* yes, extend buffer accordingly */
+
+ /* allocate memory for result */
+ destString = malloc( bufLen );
+
+ if( destString ) {
+ /* copy and translate characters as needed */
+ cp2 = destString;
+ for( cp = srcString; *cp; cp++ ) {
+ if( idx = strchr( trTbl->inChar, *cp )) { /* does character need translation ? */
+ strcpy( cp2, (trTbl->outChar)[idx - trTbl->inChar ] ); /* yes, copy the escaped character sequence */
+ cp2 += strlen((trTbl->outChar)[idx - trTbl->inChar ] );
+ } else {
+ *cp2++ = *cp; /* no, just copy the character */
+ }
+ }
+ /* terminate string */
+ *cp2 = '\0';
+ } else {
+ /* memory allocation failed */
+ exit(1);
+ }
+
+ return( destString );
+}
+
+
+int cmpHelpMsg( const void * a, const void * b )
+{
+ helpMsg_p aa = (helpMsg_p)a;
+ helpMsg_p bb = (helpMsg_p)b;
+ return strcmp( aa->title, bb->title );
+}
+
+void unescapeString( FILE * f, char * str )
+{
+ while (*str) {
+ if (*str != '\\')
+ fputc( *str, f );
+ str++;
+ }
+}
+
+/**
+ * Generate the file in help source format ( ie. the BUT file )
+ */
+
+void dumpHelp( FILE *hlpsrcF )
+{
+ int inx;
+ char *transStr;
+
+ fputs( "\\#\n * DO NOT EDIT! This file has been automatically created by genmessages.\n * Changes to this file will be overwritten.\n", hlpsrcF );
+
+ fprintf( hlpsrcF, "\n\n\\H{messageList} Message Explanations\n\n" );
+
+ /* sort in alphabetical order */
+ qsort( helpMsgs, helpMsgCnt, sizeof helpMsgs[0], cmpHelpMsg );
+
+ /* now save all the help messages */
+ for ( inx=0; inx<helpMsgCnt; inx++ ) {
+
+ transStr = TranslateString( helpMsgs[inx].title, &toUnicode );
+ fprintf( hlpsrcF, "\\S{%s} %s\n\n", helpMsgs[inx].key, transStr );
+ free( transStr );
+
+ transStr = TranslateString( helpMsgs[inx].help, &toUnicode );
+ fprintf( hlpsrcF, "%s\n\n", transStr );
+ free( transStr );
+
+ fprintf( hlpsrcF, "\n\n\\rule\n\n" );
+ }
+
+}
+
+
+int main( int argc, char * argv[] )
+{
+ FILE * hdrF;
+ FILE *inF;
+ FILE *outF;
+
+ char buff[ 4096 ];
+ char * cp;
+ int inFileIdx;
+ enum {m_init, m_title, m_alt, m_help } mode = m_init;
+ char msgName[256];
+ char msgAlt[256];
+ char msgTitle[1024];
+ char msgTitle1[1024];
+ char msgHelp[4096];
+ char *tName, *tAlt, *tTitle;
+#ifndef FLAGS
+ int flags;
+#endif
+ int i18n = 0;
+
+ /* check argument count */
+ if ( argc < 3 || argc > 4 ) {
+ fprintf( stderr, "Usage: %s [-i18n] INFILE OUTFILE\n\n", argv[0] );
+ fprintf( stderr, " -i18n is used to generate a include file with gettext support.\n\n" );
+ exit(1);
+ }
+
+ /* check options */
+ if( argc == 4 ) {
+ if( !strcmp(argv[ 1 ], "-i18n")){
+ i18n = 1;
+ inFileIdx = 2; /* second argument is input file */
+ }
+ /* inFileIdx = 2; skip over option argument */
+ } else {
+ inFileIdx = 1; /* first argument is input file */
+ }
+
+ /* open the file for reading */
+ inF = fopen( argv[ inFileIdx ], "r" );
+ if( !inF ) {
+ fprintf( stderr, "Could not open %s for reading!\n", argv[ inFileIdx ] );
+ exit( 1 );
+ }
+
+ /* open the include file to generate */
+ hdrF = fopen( "messages.h", "w" );
+ if( !hdrF ) {
+ fprintf( stderr, "Could not open messages.h for writing!\n" );
+ exit( 1 );
+ }
+
+ fputs( "/*\n * DO NOT EDIT! This file has been automatically created by genmessages.\n * Changes to this file will be overwritten.\n */\n", hdrF );
+
+ /* open the help file to generate */
+ outF = fopen( argv[ inFileIdx + 1 ], "w" );
+ if( !inF ) {
+ fprintf( stderr, "Could not open %s for writing!\n", argv[ inFileIdx ] );
+ exit( 1 );
+ }
+
+ /* Include i18n header, if needed */
+ if (i18n)
+ fprintf( hdrF, "#include \"" I18NHEADERFILE "\"\n\n" );
+
+ while ( fgets( buff, sizeof buff, inF ) ) {
+
+ /* skip comment lines */
+ if ( buff[0] == '#' )
+ continue;
+
+ /* remove trailing whitespaces */
+ cp = buff+strlen(buff)-1;
+ while( cp >= buff && isspace(*cp)) {
+ *cp = '\0';
+ cp--;
+ }
+
+ if ( strncmp( buff, "MESSAGE ", 8 ) == 0 ) {
+
+ /* skip any spaces */
+ cp = strchr( buff+8, ' ' );
+ if (cp)
+ while (*cp == ' ') *cp++ = 0;
+#ifndef FLAGS
+ if ( cp && *cp ) {
+ flags = atoi(cp);
+ }
+#endif
+ /* save the name of the message */
+ strcpy( msgName, buff + 8 );
+ msgAlt[0] = 0;
+ msgTitle[0] = 0;
+ msgTitle1[0] = 0;
+ msgHelp[0] = 0;
+ mode = m_title;
+ } else if ( strncmp( buff, "ALT", 3 ) == 0 ) {
+ mode = m_alt;
+ msgAlt[0] = 0;
+ } else if ( strncmp( buff, "HELP", 4 ) == 0 ) {
+ mode = m_help;
+ } else if ( strncmp( buff, "END", 3 ) == 0 ) {
+ /* the whole message has been read */
+
+ /* create escape sequences */
+ tName = TranslateString( msgName, &toC );
+ tTitle = TranslateString( msgTitle, &toC );
+ tAlt = TranslateString( msgAlt, &toC );
+
+ if (msgHelp[0]==0) {
+ /* no help text is included */
+ if (i18n)
+ fprintf( hdrF, "#define %s N_(\"%s\")\n", tName, tTitle );
+ else
+ fprintf( hdrF, "#define %s \"%s\"\n", tName, tTitle );
+ } else if (msgAlt[0]) {
+ /* a help text and an alternate description are included */
+ if (i18n)
+ fprintf( hdrF, "#define %s N_(\"%s\\t%s\\t%s\")\n", tName, tName, tAlt, tTitle );
+ else
+ fprintf( hdrF, "#define %s \"%s\\t%s\\t%s\"\n", tName, tName, tAlt, tTitle );
+ } else {
+ /* a help text but no alternate description are included */
+ if (i18n)
+ fprintf( hdrF, "#define %s N_(\"%s\\t%s\")\n", tName, tName, tTitle );
+ else
+ fprintf( hdrF, "#define %s \"%s\\t%s\"\n", tName, tName, tTitle );
+ }
+
+ /*free temp stzrings */
+ free( tName );
+ free( tTitle );
+ free( tAlt );
+
+ /* save the help text for later use */
+ if (msgHelp[0]) {
+ helpMsgs[helpMsgCnt].key = strdup(msgName);
+ if ( msgAlt[0] )
+ helpMsgs[helpMsgCnt].title = strdup(msgAlt);
+ else
+ helpMsgs[helpMsgCnt].title = strdup(msgTitle);
+ helpMsgs[helpMsgCnt].help = strdup(msgHelp);
+ helpMsgCnt++;
+ }
+ mode = 0;
+ } else {
+ /* are we currently reading the message text? */
+ if (mode == m_title) {
+ /* yes, is the message text split over two lines ? */
+ if (msgTitle[0]) {
+ /* if yes, keep the first part as the short text */
+ if (msgAlt[0] == 0) {
+ strcpy( msgAlt, msgTitle );
+ strcat( msgAlt, "..." );
+ }
+ /* add a newline to the first part */
+ strcat( msgTitle, "\n" );
+ }
+ /* now save the buffer into the message title */
+ strcat( msgTitle, buff );
+ } else if (mode == m_alt) {
+ /* an alternate text was explicitly specified, save */
+ if( msgAlt[ 0 ] ) {
+ strcat( msgAlt, " " );
+ strcat( msgAlt, buff );
+ } else {
+ strcpy( msgAlt, buff );
+ }
+ } else if (mode == m_help) {
+ /* we are reading the help text, save in buffer */
+ strcat( msgHelp, buff );
+ strcat( msgHelp, "\n" );
+ }
+ }
+ }
+ dumpHelp( outF );
+
+ fclose( hdrF );
+ fclose( inF );
+ fclose( outF );
+
+ printf( "%d messages\n", helpMsgCnt );
+ return 0;
+}
diff --git a/app/help/messages.in b/app/help/messages.in
new file mode 100644
index 0000000..e4c5992
--- /dev/null
+++ b/app/help/messages.in
@@ -0,0 +1,1426 @@
+############################################################
+# Various messages with help. Sorted by message content
+############################################################
+
+# chndldto.c
+MESSAGE MSG_CANT_PLACE_FROGPOINTS
+A %s cannot be placed on a turnout, circle or helix.
+ALT
+Frog|Points cannot be placed on a turnout, circle or helix.
+HELP
+The frog or points of a hand-laid turnout cannot be placed on a turnout, circle or helix track. Choose a straight or curved section of track or use the \f{Split} command to create a curve from the circle track.
+
+Refer to \k{cmdHandLaidTurnout} for detail regarding hand laid turnouts or \k{cmdSplitTrack} for detail regarding the \f{Split} command.
+END
+
+# cselect.c
+MESSAGE MSG_SEL_TRK_FROZEN
+A frozen layer contains selected
+track. Command cannot be executed.
+HELP
+This operation cannot be executed as segments of Selected track are present on a frozen layer. Track changes or deletions may be performed only on unfrozen layers. Deselect objects that appear on frozen layers or unfreeze the layers.
+
+Refer to \k{cmdLayer} for detail.
+END
+
+# ccurve.c
+MESSAGE MSG_HELIX_TURNS_GTR_0
+A Helix must have one or more loops of track.
+HELP
+A Helix cannot be created with less than one complete loop of track. Anything less than one loop is considered a section of curved track.
+END
+
+# ctext.c
+MESSAGE MSG_LARGE_FONT
+A large font has been selected.
+Large fonts may a take a while to load.
+
+Do you wish to continue?
+HELP
+A large font has been selected. Large fonts (or changing fonts sizes) may take a noticeable amount of time to load.
+
+Refer to \k{cmdText} for detail.
+END
+
+# ctodesgn.c
+MESSAGE MSG_TODSGN_DESC_NONBLANK
+All description fields present in the Turnout
+Designer must contain appropriate information.
+Correct inappropriate values and try again.
+HELP
+Turnout descriptions should be as accurate as possible. All description fields listed in the \f{Turnout Designer} must contain appropriate information.
+
+Refer to \k{cmdTurnoutNew} for detail.
+END
+
+# cgroup.c:groupOk
+MESSAGE MSG_GROUP_NONBLANK
+All fields listed in the Group dialog must contain data.
+Please enter missing values and try again.
+HELP
+The \f{Group} dialog shows the Manufacturer, Description and part number (Title) of the new definition. Initial values are based on selected turnouts and structures or on the last \f{Ungroup}ed object. The dialog also contains a toggle button (\f{Replace with new group}?), which is used if you want to replace the selected objects with the new definition. All fields listed in this dialog window must contain data.
+
+Refer to \k{cmdGroup} for detail.
+END
+
+# ctodesgn.c
+MESSAGE MSG_TODSGN_VALUES_GTR_0
+All values specified in the Turnout Designer must be
+greater than 0. Correct inappropriate values and try again.
+HELP
+Turnout dimensions should be as accurate as possible. All values specified in the \f{Turnout Designer} must be greater than 0.
+
+Refer to \k{cmdTurnoutNew} for detail.
+END
+
+MESSAGE MSG_CURVE_OUT_OF_RANGE
+Angle must be between 0° and 360°.
+HELP
+The angle specified for a curve must be between 0\u00B0 and 360\u00B0.
+END
+
+# dcustmgm.c
+MESSAGE MSG_CUSTMGM_DELETE_CONFIRM
+Are you sure you want to delete the
+%d definition(s)?
+ALT
+Are you sure you want to delete the
+NNN definition(s)?
+HELP
+You are about to delete a custom turnout or structure design from the \f{Custom Design} file (\c{xtrkcad.cus}) file. This action cannot be undone.
+
+Refer to \k{installDir} and \k{workDir} for an explanation of the files used by
+\e{XTrackCAD}.
+END
+
+# dbitmap.c
+MESSAGE MSG_WBITMAP_FAILED
+Bitmap create or write function failed.
+HELP
+Your attempt to create or write a bitmap file failed. This could be due to the bitmap being too large or a lack of system resources. Try creating a smaller Bitmap or freeing system resources by closing other applications and dialog windows.
+END
+
+# dbitmap.c
+MESSAGE MSG_BITMAP_TOO_LARGE
+Bitmap is too large.
+HELP
+A Bitmap must be less than 32000 pixels in height or width. Try increasing the DPI (or DPCM) value.
+
+Refer to \k{cmdOutputbitmap} for detail.
+END
+
+# cprofile.c
+MESSAGE MSG_CHANGE_ELEV_MODE
+Cannot change elevation mode.
+HELP
+In the \f{Profile} command, the \f{Elevation} mode for this \e{endpoint} can be change only if it is \f{Defined}, \f{Ignored} or \f{None}. The \f{Elevation} command can be used to change this \e{endpoint}.
+
+Refer to \k{cmdElev} for detail.
+END
+
+# csnap.c
+MESSAGE MSG_GRID_ENABLE_SPACE_GTR_0
+Cannot Enable Grid; spacing must be greater than 0
+HELP
+Before the horizontal or vertical \f{Snap Grid} can be \f{Enable}d, the corresponding \e{Spacing} value(s) on the \f{Grid} dialog must be set to a value greater than 0.
+
+Refer to \k{cmdGrid} for detail.
+END
+
+# dlayer.c
+MESSAGE MSG_LAYER_FREEZE
+Cannot freeze current layer
+HELP
+The current \f{Layer} is where most new objects are created. It's not possible to freeze this layer, since it would not be able to create objects. Change the current \f{Layer} to some other \f{Layer} before trying to freeze this Layer.
+
+Refer to \k{cmdLayer} for detail.
+END
+
+# cgroup.c:doGroup
+MESSAGE MSG_CANT_GROUP_BUMPER1
+Cannot Group Bumper Track. The track has been unselected.
+HELP
+Bumper tracks (tracks with 1 endpoint) are not supported by the Group command.
+END
+
+# cgroup.c:doGroup
+MESSAGE MSG_CANNOT_GROUP_TRACK
+Cannot Group selected track.
+HELP
+Group objects are formed from Straight, Curved, Turnout or Sectional track. The selected objects include a track which is not one of these. Reselect the objects, including only track segments of these types.
+
+Refer to \k{cmdGroup} for detail.
+END
+
+# dlayer.c
+MESSAGE MSG_LAYER_HIDE
+Cannot hide current layer
+HELP
+The current \f{Layer} is where most new objects are created. It's not possible to hide this layer, since it would not be possible to see the objects. Change the current \f{Layer} to some other \f{Layer} before trying to hide this Layer.
+
+Refer to \k{cmdLayer} for detail.
+END
+
+# cjoin.c track.c:getTrackParams/PARAMS_..._JOIN
+MESSAGE MSG_JOIN_EASEMENTS
+Cannot Join; Easements do not align or abut.
+HELP
+You are trying to \f{Join} two \e{easement} curves. This can be achieved only if the two curves abut and are aligned. Otherwise, you can delete the \e{easement} curves and try to \f{Join} to connected tracks.
+
+Refer to \k{cmdJoin} for detail.
+END
+
+# cjoin.c
+MESSAGE MSG_TRK_ALREADY_CONN
+Cannot Join; %s track is already connected.
+ALT
+First|Second track is already connected.
+HELP
+To \f{Join} one track with another, the \e{endpoints} selected for connection cannot be connected with any other track. Pick another track with an unconnected \e{endpoint} or disconnect one of the \e{endpoints} using the \f{Split} command.
+
+Refer to \k{cmdJoin} for detail regarding the \f{Join} command or \k{cmdSplitTrack} for detail regarding the \f{Split} command.
+END
+
+# cturntbl.c
+MESSAGE MSG_JOIN_TURNTABLE
+Cannot join from a turntable, try to a turntable
+HELP
+You cannot select a \f{Turntable} as the second track in \f{Join} command. If you wish to \f{Join} to a \f{Turntable} then select the \f{Turntable} as the first track in the \f{Join} command.
+
+Refer to \k{cmdJoin} for detail.
+END
+
+# cjoin.c
+MESSAGE MSG_JOIN_SAME
+Cannot Join; Selected endpoints are on same track.
+HELP
+You are trying to \f{Join} a section of track with itself. Different tracks must selected when using the \f{Join} command.
+
+Refer to \k{cmdJoin} for detail.
+END
+
+# cjoin.c
+MESSAGE MSG_SELECTED_TRACKS_PARALLEL
+Cannot Join; Selected tracks are parallel.
+HELP
+These tracks cannot be joined as they are parallel to each other and the selected \e{endpoints}, point in opposite directions. To \f{Join} these two tracks, pick \e{endpoints} that point in the same direction.
+
+Refer to \k{cmdJoin} for detail.
+END
+
+# dprmfile.c
+MESSAGE MSG_PRMFIL_OPEN_NEW
+Cannot open New Parameter File: %s
+ALT
+Cannot open New Parameter File: FILENAME
+HELP
+During the processing of \f{Parameter Files} after updating to a new version of
+\e{XTrackCAD}, one of updated \f{Parameter Files} could not be found. Check that the installation had no errors. You can use the \f{Parameter Files} dialog to locate the parameter file.
+
+Refer to \k{cmdPrmfile} for detail.
+END
+
+# dlayer.c
+MESSAGE MSG_LAYER_SEL_FROZEN
+Cannot select a frozen layer
+HELP
+The current \f{Layer} is where most new objects are created. It's not possible to select a frozen \f{Layer}, since it would not be possible to create objects. Unfreeze this \f{Layer} before trying to make this the current \f{Layer}.
+
+Refer to \k{cmdLayer} for detail.
+END
+
+# csnap.c
+MESSAGE MSG_GRID_SHOW_SPACE_GTR_0
+Cannot Show Grid; spacing must be greater than 0
+HELP
+Before the \f{Snap Grid} can be \f{Show}n, corresponding horizontal or vertical \e{Spacing} value(s) on the \f{Grid} dialog must be set to a value greater than 0.
+
+Refer to \k{cmdGrid} for detail.
+END
+
+# track.c
+MESSAGE MSG_CANT_SPLIT_TRK
+Cannot split %s track
+ALT
+Cannot split TYPE track
+HELP
+This type of track cannot be \f{Split}. Only Straight, Curved, Circle and Easement tracks can be \f{Split}. To \f{Split} a Turnout, hold down the Shift key then \e{Left-Click} on the position where the track should be \f{Split}.
+
+Refer to \k{cmdSplitTrack} for detail.
+END
+
+# dcustmgm.c
+MESSAGE MSG_CUSTMGM_CANT_WRITE
+Cannot write to parameter file: %s
+ALT
+Cannot write to parameter file: FILENAME
+HELP
+The specified parameter file can not be written to. Make sure the file and or directory is not marked as read only.
+END
+
+MESSAGE MSG_CARIMP_DUP_INDEX
+Car Index number duplicated.
+HELP
+Each Car in your inventory must have a unique index value. If a duplicate index number is found during the \f{Import} process it will be replaced with a new, unused value.
+END
+
+# doption.c
+MESSAGE MSG_CONN_PARAMS_TOO_SMALL
+Connection parameters reset to minimum values.
+HELP
+The parameters \e{Minimum Track Length}, \e{Connection Angle} and \e{Connection Distance} have minimum values that cannot be set to smaller values. The minimum values are 0.1"/0.254cm, 1\u00B0 and 0.1"/0.254cm respectively.
+
+Refer to \k{cmdPref} for detail.
+END
+
+# fileio.c
+MESSAGE MSG_CANT_PASTE
+Copy/Paste buffer is empty. There is nothing to Paste.
+HELP
+An attempt was made to \f{Paste} an object onto the layout however the Copy/Paste buffer was empty. This error generally occurs when the \f{Paste} command is executed without first executing the \f{Copy} command.
+
+Refer to \k{editM} for detail.
+END
+
+# ctodesgn.c
+MESSAGE MSG_TODSGN_CROSSOVER_TOO_SHORT
+Crossover length is too short. Correct
+inappropriate value(s) and try again.
+HELP
+The length of crossover segments must be greater than the track gauge.
+END
+
+# curves
+MESSAGE MSG_CURVE_TOO_LARGE
+Curved track is too large.
+HELP
+The length of the curved track is limited to sum of the room dimensions. This limitation prevents creation of curves that are unreasonably large. Adjust the mouse position to create a smaller Curve.
+END
+
+# ctodesgn.c
+MESSAGE MSG_TODSGN_REPLACE
+Definition name is already in use. Saving this
+definition replaces the existing definition.
+
+Do you want to continue?
+HELP
+The definition you're attempting to create uses the same name as an existing
+definition. Saving the definition with the same name will cause \e{XTrackCAD} to replace the existing definition, making the existing definition inaccessible. If the previous definition must be preserved, then choose a different name for the new definition. If necessary, the \f{Custom Management} dialog can be used to change definition names.
+
+Refer to \k{cmdCustmgm} for detail.
+END
+
+# draw.c
+MESSAGE MSG_SAVE_CHANGES
+Do you want to save the changes made to your Layout?
+HELP
+The \f{Exit} command was selected without first saving changes that have been made to the layout. This notice gives you the chance to save your changes before the program ends.
+END
+
+MESSAGE MSG_CARIMP_DUP_COLUMNS
+Duplicate column headers found in Car Import file.
+HELP
+The \f{Car Import} function reads car values from a Comma-Separated-Value (CSV) file. The import file must contain headers for at least the \e{Scale}, \e{Prototype}, \e{Manufacturer} and \e{Partno} columns. In addition, the following column headers may also be included: \e{Index}, \e{Type}, \e{Description}, \e{Roadname}, \e{Repmark}, \e{Number}, \e{Options}, \e{CarLength}, \e{CarWidth}, \e{CoupledLength}, \e{TruckCenter}, \e{Color}, \e{PurchPrice}, \e{CurrPrice}, \e{Condition}, \e{PurchDate}, \e{ServiceDate} and \e{Notes}.
+
+It appears the CSV file that you're attempting to \f{Import} contains more than one row of column headers. Review the CSV files content and ensure only one row of header data exists.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+# cprofile.c
+MESSAGE MSG_EP_ON_PATH
+Endpoint already on Path.
+HELP
+An \e{endpoint} that is already on the \f{Profile Path} has been selected. Select a different \e{endpoint}; one that is on a track that is not drawn in Purple.
+
+Refer to \k{cmdProfile} for detail.
+END
+
+# fileio.c
+MESSAGE MSG_UPGRADE_VERSION1
+File version %ld is greater than supported
+version %d. You need to upgrade %s
+to at least version %s.
+HELP
+The layout file that you're attempting to load was created using a newer version
+of \e{XTrackCAD}. In order to load this file it will be necessary to upgrade your version of \e{XTrackCAD} to at least the version identified within the error message.
+
+Take full advantage of the latest features within \e{XTrackCAD} by visiting the \W{http://www.xtrkcad.org/}{\e{XTrackCAD} Fork Website} and downloading the latest release.
+END
+
+#fileio.c
+MESSAGE MSG_UPGRADE_VERSION2
+File version %ld is greater than supported
+version %d. You need to upgrade your
+version of %s
+HELP
+The layout file that you're attempting to load was created using a newer version of \e{XTrackCAD}. In order to load this file it will be
+necessary to upgrade your version of \e{XTrackCAD} to at least the version identified within the error message.
+
+Take full advantage of the latest features within \e{XTrackCAD} by visiting the \W{http://www.xtrkcad.org/}{\e{XTrackCAD} Fork Website} and downloading the latest release.
+END
+
+# chndldto.c
+MESSAGE MSG_MOVE_POINTS_OTHER_SIDE
+Frog angle prevents placement of points.
+Move points to opposite side of frog.
+HELP
+The frog angle prevents points from being placed on this side of the frog. Place points on opposite side of frog or retry this command and create the frog in the opposite direction.
+
+Refer to \k{cmdHandLaidTurnout} for detail.
+END
+
+# cturntbl.c
+MESSAGE MSG_NO_ROOM_BTW_TRKS
+Insufficient space between existing stall tracks.
+HELP
+There is insufficient space between the two existing turntable stall tracks to place a new stall track. Either place the new stall track on a different part of the turntable or decrease the \e{Turntable Angle} using the \f{Command Options} dialog.
+
+Refer to \k{cmdTurntable} for detail regarding turntables or \k{cmdCmdopt} for detail regarding the \f{Command Options} dialog and \e{Turntable Angle}s.
+END
+
+# track.c:connectTracks
+MESSAGE MSG_JOIN_DIFFER_ELEV
+Joining tracks with differing elevations (%0.2f)
+ALT
+Joining tracks with differing elevations (N.NNN)
+HELP
+You are connecting two \e{endpoints} which differ in heights by N.NNN. The elevation of the connection will be the average of the two heights. You should check if this is a problem.
+END
+
+# cselect.c:cmdMoveDescription
+MESSAGE MSG_DESC_NOT_VISIBLE
+Label descriptions not visible
+HELP
+The \f{Move Description} command can only be used when labels are visible on the layout. Labels will not be visible when the \f{Label Scale} is set to a smaller value than the current drawing scale or when no items are enabled in the \f{Label Enable} section of the \f{Display Options} dialog.
+
+Check the \f{Display Options} dialog (\f{Options>Display}) to determine if;
+
+\u000
+
+\b the \f{Label Scale} is set to a value smaller than or equal to the current drawing scale.
+
+\b at least one attribute within the \f{Label Enable} section is selected. You will of course want to ensure the type of label you wish to move is selected.
+
+\u000
+
+Refer to \k{cmdMoveLabel} for detail regarding \f{Description} movement or \k{cmdDisplay} for detail regarding \f{Display} attributes.
+END
+
+MESSAGE MSG_OBJECT_TOO_SHORT
+Length of object is too short.
+HELP
+The specified length for the object being modified is too short. Increase the objects length.
+END
+
+# cprint.c
+MESSAGE MSG_PRINT_MAX_SIZE
+Maximum allowed page size is %s x %s
+ALT
+Maximum allowed page size is W x H
+HELP
+Values for \f{Page Width} and \f{Height} can be manually entered thus overriding maximum values. For example, smaller values could be specified if each printed page is to contain an integral number of feet. Values larger than the selected paper size multiplied by the \e{Scale} cannot be entered.
+
+Refer to \k{cmdPrint} for detail.
+END
+
+# dprmfile.c
+MESSAGE MSG_PRMFIL_NO_CONTENTS
+New Parameter File has no CONTENTS line: %s
+ALT
+New Parameter File has no CONTENTS line: FILENAME.
+HELP
+Each \f{Parameter Files} contains a line which identifies the contents. The specified file is missing this line.
+
+Please report this error to the \e{XTrackCAD} project development team at SourceForge. The process for reporting errors is outlined in \k{bugs}.
+END
+
+MESSAGE MSG_NO_CARS
+No Cars are defined for the current scale.
+
+Do you want to use the Car Inventory dialog?
+HELP
+No Cars are defined for the current scale. Use the dialog to select cars of the current scale and add them to the \f{Car Inventory}.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+# dcar.c
+MESSAGE MSG_NO_CARPROTO
+No Car Prototypes are defined.
+Load a Prototype definition file using the
+Parameter Files dialog or create a Prototype
+definition using the Car Prototype dialog.
+HELP
+No \f{Car Prototypes} are defined. Load a car prototype definition file (such as protoam.xtp) using the \f{Parameter Files} dialog or create a prototype definition using the \f{Car Prototype} dialog.
+
+Refer to \k{cmdPrmfile} for detail regarding the \f{Parameter Files} or \k{carprototype} for detail regarding the \f{Car Prototype} dialog.
+END
+
+MESSAGE MSG_CARIMP_NO_DATA
+No data present in Car Import file.
+HELP
+The \f{Car Import} function reads car values from a Comma-Separated-Value (CSV) file. The import file must contain headers for at least the \e{Scale}, \e{Prototype}, \e{Manufacturer} and \e{Partno} columns. In addition, information relative to at least one car must be included in the file otherwise this error occurs.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+# cprint.c
+MESSAGE MSG_PRINT_NO_PAGES
+No pages selected for printing.
+HELP
+Pages are selected for printing by clicking on the print grid on the layout. Use the \f{Zoom Out} command to bring more of the layout into view (\K{cmdZoom}). The print grid can be moved using the \e{Shift+Left+Drag} command or rotated using the \e{Shift+Right+Drag} command.
+
+Refer to \k{cmdPrint} for detail.
+END
+
+# cprofile.c
+MESSAGE MSG_NO_PATH_TO_EP
+No path between Profile and selected endpoint.
+HELP
+There is no path of track between the end of the \f{Profile} and the \e{endpoint} you have clicked on.
+
+Refer to the \k{cmdProfile} for detail.
+END
+
+# dprmfile.c
+MESSAGE MSG_PRMFIL_NO_MAP
+No Parameter File Map for %s
+ALT
+No Parameter File Map for CONTENTS
+HELP
+The parameter file for \f{CONTENTS} has been moved or deleted. Use the \f{Parameter Files} dialog to locate the \f{Parameter Files}.
+
+Refer to \k{cmdPrmfile} for detail.
+END
+
+# various
+MESSAGE MSG_NO_SELECTED_TRK
+No track(s) selected!
+HELP
+The current command operates on \f{Select}ed tracks of which there are none. \f{Select} the desired track and try the command again.
+
+Refer to \k{cmdSelect} for detail.
+END
+
+# dcmpnd.c:refreshCompound
+MESSAGE MSG_NO_TURNOUTS_AVAILABLE
+No %s are available.
+ALT
+No Turnouts|Structures are available.
+HELP
+The \f{Update Turnouts and Structures} command updates (or refreshes) selected turnouts, sectional tracks and structures on your layout with the current definitions from the loaded parameter files (\K{cmdPrmfile}). Each selected object that is found in a parameter file is updated with the current definition.
+
+If an object can not be found or if the new definition does not fit (same number of endpoints and all the endpoints have the same position and angle) then a dialog is displayed which contains suitable definitions that you can choose from. In the case of turnouts, this list is populated with turnouts having the same number of endpoints as the selected turnout. If turnouts with the same number of endpoints exist then this message is displayed.
+
+Refer to \k{cmdRefreshSpecial} for detail.
+END
+
+# dcar.c
+MESSAGE MSG_CARDESC_VALUE_ZERO
+Numeric values on the Car Description
+dialog must be greater than 0.
+HELP
+Numeric values on the \f{Car Description} dialog (Car Length, Car Width, Truck Centers, Coupled Length and Coupler Length) must be greater than zero.
+
+Refer to \k{cmdTrain} for detail.
+END
+
+MESSAGE MSG_MOVE_OUT_OF_BOUNDS
+Object has moved beyond room boundaries.
+HELP
+The last operation moved the object outside of room boundaries; room width and height. The \f{Undo} command can be used to move the object back.
+
+Refer to \k{cmdLayout} for detail regarding room boundaries and \k{cmdUndo} for detail regarding the \f{Undo} command.
+END
+
+# cparalle.c
+MESSAGE MSG_PARALLEL_SEP_GTR_0
+Parallel separation must be greater than 0.
+HELP
+A parallel track with a separation of 0 or less cannot be created. Specify a positive value in the \f{Separation} field that appears in the Status Bar.
+
+Refer to \k{cmdParallel} for detail.
+END
+
+# dcar.c
+MESSAGE MSG_CARPART_DUPNAME
+Part Number for this Manufacturer already exists.
+
+Do you want to update it?
+HELP
+The \e{Part} definition you're attempting to create uses the same Manufacturer and Part Number as an existing definition. Saving the
+definition with the same Manufacturer and Part Number will cause \e{XTrakCAD} to update the existing definition. If the previous definition must be preserved, then choose a different Part Number for the new definition.
+
+Refer to \k{carpart} for detail.
+END
+
+# param.c
+MESSAGE MSG_PLAYBACK_LISTENTRY
+Playback: Cannot find list entry: %s
+ALT
+Playback: Cannot find list entry: NAME
+HELP
+This error is most likely caused by trying to \f{Playback} an incompatible \e{XTrackCAD} recording or demo file.
+
+Refer to \k{macroM} for detail.
+END
+
+# macro.c
+MESSAGE MSG_PLAYBACK_VERSION_UPGRADE
+Playback file version %ld is
+greater than supported version %d
+You need to upgrade your version of %s
+HELP
+The layout file that you're attempting to load was created using a newer version of \e{XTrackCAD}. In order to load this file it will be
+necessary to upgrade your version of \e{XTrackCAD} to at least the version identified within the error message.
+
+Take full advantage of the latest features within \e{XTrackCAD} by visiting the \W{http://www.xtrkcad.org/}{\e{XTrackCAD} Fork Website} and downloading the latest release.
+END
+
+# draw.c
+MESSAGE MSG_DOMOUSE_BAD_OP
+Playback: unknown action %d
+ALT
+Playback: unknown action NNN
+HELP
+This error is most likely caused by trying to \f{Playback} an incompatible \e{XTrackCAD} recording or demo file.
+
+Refer to \k{macroM} for detail.
+END
+
+# chndldto.c
+MESSAGE MSG_MOVE_POINTS_AWAY_CLOSE
+Points are to close to frog; move away.
+HELP
+The points are being placed too close to the frog. Move the points away from the frog and try again.
+
+Refer to \k{cmdHandLaidTurnout} for detail.
+END
+
+# drawgeom.c
+MESSAGE MSG_POLY_SHAPES_3_SIDES
+Poly shapes must have at least 3 sides.
+HELP
+Polygons and Poly Lines must have at least 3 sides. By moving one of the corners close to another corner you're attempting to merge the corners and create a Poly shape with only 2 sides. Try moving the other corner to the new position first.
+END
+
+# dcar.c
+MESSAGE MSG_CARPROTO_DUPNAME
+Prototype name already exists.
+
+Do you want to update it?
+HELP
+The \e{Prototype} definition you're attempting to create uses the same name as an existing definition. Saving the definition with the
+same name will cause \e{XTrackCAD} to update the existing definition. If the previous definition must be preserved, then choose a different Part Number for the new definition.
+
+Refer to \k{carprototype} for detail.
+END
+
+# ccurve.c
+MESSAGE MSG_RADIUS_GTR_0
+Radius must be greater than 0.
+HELP
+It's not possible to create a Circle or Helix with a radius of 0\u00B0 or less. Specify a positive value in the \f{Radius} field that appears in the Status Bar.
+END
+
+#cselect.c
+MESSAGE MSG_RESCALE_TOO_BIG
+Rescaled tracks do not fit within layouts room parameters
+(Height and width). The layouts room parameters should be
+set to at least %s by %s.
+HELP
+While using the \f{Change Scale} command to enlarge the layout, \e{XTrackCAD} determined that rescaled tracks do not fit within the layout rooms parameters. Using the \f{Layout} dialog, the rooms parameters (Height and width) should be set so as to accommodate the rescaled track.
+
+Refer to \k{cmdLayout} for detail regarding \f{Layout} options or \k{cmdRescale} for detail regarding the \f{Change Scale} command.
+END
+
+MESSAGE MSG_CARIMP_MISSING_COLUMNS
+Required column headers missing from Car Import file.
+HELP
+The \f{Car Import} function reads car values from a Comma-Separated-Value (CSV) file. The import file must contain headers for at least the \e{Scale}, \e{Prototype}, \e{Manufacturer} and \e{Partno} columns. In addition, the following column headers may also be included: \e{Index}, \e{Type}, \e{Description}, \e{Roadname}, \e{Repmark}, \e{Number}, \e{Options}, \e{CarLength}, \e{CarWidth}, \e{CoupledLength}, \e{TruckCenter}, \e{Color}, \e{PurchPrice}, \e{CurrPrice}, \e{Condition}, \e{PurchDate}, \e{ServiceDate} and \e{Notes}.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+# cjoin.c
+MESSAGE MSG_2ND_TRK_NOT_SEL_UNSEL
+Second track must be %s.
+ALT
+Second track must be selected|unselected
+HELP
+The \f{Move To Join} command moves the selected tracks so an \e{endpoint} is joined with the \e{endpoint} of an unselected track. If you choose the selected \e{endpoint} first then you must choose an unselected \e{endpoint} second, and vice versa.
+
+Refer to \k{joinTrackMove} for detail.
+END
+
+# cprint.c
+MESSAGE MSG_OUT_OF_BOUNDS
+Selected page is out of bounds.
+HELP
+During execution of the \f{Print} command an attempted was made to select a page that's outside the layouts boundaries.
+
+Refer to \k{cmdLayout} for detail regarding layout boundaries or \k{cmdPrint} for detail regarding the \f{Print} command.
+END
+
+# ctext.c
+MESSAGE MSG_SEL_POS_FIRST
+Select position prior to entering Text.
+HELP
+The position where text is to be placed on the layout must be selected prior to text entry. The position is select by \e{Left-Click}ing on the layout at the point where the text is to appear. Desired text is entered after the position is selected. If necessary, the location can be changed once text entry begins by \e{Left-Click+Drag}ing the text to any desired position on the layout.
+
+Refer to \k{cmdText} for detail.
+END
+
+# dcar.c
+MESSAGE MSG_CARPROTO_BADSEGS
+Selected shapes must define a rectangular
+area with length greater than height.
+ALT
+Selected shapes must define a rectangular area ...
+HELP
+The \f{Import} command (Button) on the \f{Car Prototype} dialog is used to create the image of an car from the shapes selected on the layout prior to opening the \f{Car Prototype} dialog. The car is assumed to be oriented horizontally so its length must be greater than its height. The selected shapes do not meet this requirement.
+
+Refer to \k{carprototype} for detail.
+END
+
+# cpull.c
+MESSAGE MSG_TOO_FAR_APART_DIVERGE
+Selected tracks deviate too much or
+are too far apart from each other.
+HELP
+The \f{Connect} command is used to remove small gaps that may result when using sectional track. The chosen sectional track \e{endpoints} must be close together and nearly aligned. The selected tracks deviate too much or are too far apart from each other.
+
+Refer to \k{cmdConnect} for detail.
+END
+
+# misc.c
+MESSAGE MSG_COMMAND_DISABLED
+Specified command disabled.
+HELP
+The specified command has been disabled in error.
+
+Please report this error to the \e{XTrackCAD} project development team at SourceForge. The process for reporting errors is outlined in \k{bugs}.
+END
+
+# cturnout.c:splitTurnout
+MESSAGE MSG_SPLIT_POS_BTW_MERGEPTS
+Split position between Turnout Points
+HELP
+The \f{Split} position must be between an endpoint and the position where the turnout's track segments diverge (the turnout points). Select a position closer to the endpoint.
+END
+
+# cturnout.c:splitTurnoutCheckPath
+MESSAGE MSG_SPLIT_PATH_NOT_UNIQUE
+Split position not on unique path
+HELP
+The \f{Split} position must be between an endpoint and the position where the turnout's track segments diverge (the turnout points). Select a position closer to the endpoint.
+END
+
+MESSAGE MSG_CARIMP_MISSING_DIMS
+The following car has no dimensions and a
+Car Part description can not be found.
+
+%s
+
+Do you wish to continue importing other Cars?
+HELP
+The car import file does not specify car dimensions and the specified \e{Partno} can not be found. Edit the import file and either add
+car dimensions or add/update the \e{Partno}. This will allow \e{XTrackCAD} to locate information for the car being imported.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+MESSAGE MSG_CARIMP_MISSING_PARTNO
+The following car has no Part Number
+
+%s
+
+Do you wish to continue importing other Cars?
+HELP
+The car import file must contain headers for at least the \e{Scale}, \e{Prototype}, \e{Manufacturer} and \e{Partno} columns. In addition, car information relative to these columns must be included in each line of the file otherwise this error will occur.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+MESSAGE MSG_CARIMP_IGNORED_COLUMN
+The following column in the Car Import file will be ignored:
+
+%s
+HELP
+An invalid column in the Car Import file will be ignored. Valid column names are:
+
+\e{Index}, \e{Scale}, \e{Manufacturer}, \e{Type}, \e{Partno}, \e{Prototype}, \e{Description}, \e{Roadname}, \e{Repmark}, \e{Number}, \e{Options}, \e{CarLength}, \e{CarWidth}, \e{CoupledLength}, \e{TruckCenter}, \e{Color}, \e{PurchPrice}, \e{CurrPrice}, \e{Condition}, \e{PurchDate}, \e{ServiceDate} and \e{Notes}.
+
+Refer to \k{cmdCarinv} for detail.
+END
+
+# ctrain.c
+MESSAGE MSG_CANT_MOVE_UNDER_TRAIN
+The position of a turnout or turntable cannot
+be changed while occupied by a train.
+HELP
+The position of a turnout or turntable cannot be changed while occupied by a train.
+
+Refer to \k{cmdTrain}, \e{Turnouts and Turntables} for detail.
+END
+
+# cstruct.c
+MESSAGE MSG_STRUCT_NO_STRUCTS
+There are no structures to choose from in the structure
+selection list. Please check your SCALE, select the
+<File|Parameter Files> menu to load a Parameter File or
+create a new Structure with the Group command.
+HELP
+This error occurs when;
+
+\b no structures are available in the structure selection list or;
+
+\b the scale setting of the layout and \f{Parameter File}s does not match.
+
+Using the \f{File>Parameter Files} menu, check which Parameter files are loaded. Ensure the scale of the loaded files match that of the layout. Alternately a new Structure could be created using the \f{Group} command.
+
+Refer to \k{cmdPrmfile} for detail regarding \f{Parameter File}s or \k{cmdGroup} for detail regarding the \f{Group} command.
+END
+
+# cturnout.c
+MESSAGE MSG_TURNOUT_NO_TURNOUT
+There are no turnouts to choose from in the turnout
+selection list. Please check your SCALE, select the
+<Manage|Turnout Designer> menu to enter a new turnout
+or select the <File|Parameter Files> menu to load a
+Parameter File
+HELP
+This error occurs when;
+
+\b no turnouts are available in the turnouts selection list or;
+
+\b the scale setting of the layout and \f{Parameter File}s does not match.
+
+Using the \f{File>Parameter Files} menu, check which Parameter files are loaded. Ensure the scale of the loaded files match that of the layout. Alternately a new turnout could be created using the \f{Turnout Designer} command.
+
+Refer to \k{cmdPrmfile} for detail regarding \f{Parameter File}s or \k{cmdTurnoutNew} for detail regarding the \f{Turnout Designer} command.
+END
+
+# track.c:pickUnconnectedEndPt
+MESSAGE MSG_NO_UNCONN_EP
+There are no unconnected end points for this track
+HELP
+The current command operates on the unconnected \e{endpoint} of a track, but the \e{endpoints} of the chosen track are all connected to other tracks. Use the \f{Split} command to disconnect the desired \e{endpoint} of this track or choose another track.
+
+Refer to \k{cmdSplitTrack} for detail.
+END
+
+# cpull.c
+MESSAGE MSG_PULL_FEW_SECTIONS
+There are too few sections in this loop.
+HELP
+The \f{Connect} command operates by adding small gaps between other track to make up for the larger gap between the tracks you have selected. In this case you are attempting to close a loop of track with to few sections. Try creating a loop with more sectional track pieces.
+
+Refer to \k{cmdConnect} for detail.
+END
+
+# cundo.c
+MESSAGE MSG_NO_REDO
+There is nothing to redo!
+HELP
+Either the \f{Undo} command has not been used or another command has been used since, thus no Undo operations are available to be undone.
+
+Refer to \k{cmdUndo} for detail.
+END
+
+# cundo.c
+MESSAGE MSG_NO_UNDO
+There is nothing to undo!
+HELP
+Either no operations have been performed since the current file was opened or all previous operations (up to 10) have been undone.
+
+Refer to \k{cmdUndo} for detail.
+END
+
+# cgroup.c:groupOk
+MESSAGE MSG_TOOMANYSEGSINGROUP
+Too many segments in Group.
+HELP
+A group is limited to a maximum of 128 track segments. The number of segments within the selected group of tracks exceed this number. Select a smaller number of tracks then try again.
+
+Refer to \k{cmdGroup} for detail.
+END
+
+# cmodify.c
+MESSAGE MSG_CANNOT_CHANGE
+Track cannot be changed.
+HELP
+Modifications can only be made to straight or curved tracks.
+END
+
+# cturntbl.c
+MESSAGE MSG_POINT_INSIDE_TURNTABLE
+Track endpoint is within turntable radius.
+HELP
+An attempt has been made to create the \e{endpoint} of a track within the radius of the \f{Turntable}. Move the \e{endpoint} of the track (mouse pointer) outside of the radius of the \f{Turntable}.
+
+Refer to \k{cmdTurntable} for detail.
+END
+
+# chndldto.c
+MESSAGE MSG_MOVE_POINTS_AWAY_NO_INTERSECTION
+Track intersection not possible; move points away from frog.
+HELP
+The track angle at the current point position does not intersect with the angle of the diverging leg of the new turnout. The points need to be relocated to a position that will allow the angle of the track to intersect the angle of the diverging leg of the new turnout.
+
+Refer to \k{cmdHandLaidTurnout} for detail.
+END
+
+# various
+MESSAGE MSG_TRK_TOO_SHORT
+%strack is too short by %0.3f
+ALT
+Track is too short by N.NNN
+HELP
+The operation will create a track that is shorter than the minimum length specified on the \f{Preferences} dialog. Adjust the position of the mouse to increase the length of the track by moving away from the \e{endpoint}.
+
+Refer to \k{cmdPref} for detail.
+END
+
+# various
+MESSAGE MSG_RADIUS_LSS_EASE_MIN
+Track radius (%s) is smaller than
+easement minimum (%s).
+ALT
+Track radius (N.NNN) is smaller than
+easement minimum (N.NNN).
+HELP
+An attempt was made to create a curved track with a radius smaller than the minimum specified in the \f{Easement} dialog. Try moving the mouse to different position, creating a curve with a larger radius.
+
+Refer to \k{cmdEasement} for detail.
+END
+
+# track.c
+MESSAGE MSG_CANT_MODIFY_FROZEN_TRK
+Tracks in a frozen layer cannot be modified.
+HELP
+This operation cannot be executed as the selected track is present on a frozen layer. Track modifications may be performed only on unfrozen layers. Move the object to a \f{Layer} that's not frozen or unfreeze the layer.
+
+Refer to \k{cmdLayer} for detail.
+END
+
+#ctodesgn.c
+MESSAGE MSG_SEGMENTS_DIFFER
+Turnout definition contains non-track segments.
+
+Do you want to include them in this update?
+HELP
+Turnout definitions can include lines and other shapes that represent switch machines, switch stands, roadbed or other objects. Such items can be include when editing Turnout definitions. These same items can also be removed if there's a need to start over again.
+
+Refer to \k{cmdCustmgm} for detail.
+END
+
+# cturntbl.c
+MESSAGE MSG_TURNTABLE_DIAM_GTR_0
+Turntable diameter must greater than 0.
+HELP
+It's not possible to create a turntable with a diameter of less than or equal to 0. Specify a positive value in the \f{Diameter} field that appears in the Status Bar.
+END
+
+# cundo.c
+MESSAGE MSG_UNDO_ASSERT
+Undo assertion failure %s:%d
+Val = %ld(%lx)
+%s
+Please report this error to the XTrackCAD project development team at SourceForge.
+HELP
+Please report this error to the \e{XTrackCAD} project development team at SourceForge. The process for reporting errors is outlined in \k{bugs}.
+END
+
+# fileio.c
+MESSAGE MSG_PROG_CORRUPTED
+Critical file damaged!
+
+%s is corrupt.
+
+Please reinstall software.
+HELP
+A critical file is corrupt. Unfortunately it will be necessary to reinstall the software or contact the XTrackCAD project development team at SourceForge in order to overcome this error.
+
+Please report this error to the \e{XTrackCAD} project development team at SourceForge. The process for reporting errors is outlined in \k{bugs}.
+END
+
+# track.c
+MESSAGE MSG_PT_IS_NOT_TRK
+[%s %s] is not a track.
+ALT
+[X Y] is not a track
+HELP
+The current command operates on a track object and a track was not found at the current location (given as X and Y).
+END
+
+# dbitmap.c
+MESSAGE MSG_BITMAP_SIZE_WARNING
+You have specified a large Bitmap.
+
+Are you sure you want to continue?
+HELP
+Bitmaps can use a large amount of system resources. They may also take a long time to generate and create a large file.
+
+Refer to \k{cmdOutputbitmap} for detail.
+END
+
+
+
+############################################################
+# Various messages without help or specific origin.
+############################################################
+
+# various
+MESSAGE MSG_CARINV_DELETE_CONFIRM
+Are you sure you want to delete these %d car(s)?
+#NOHELP
+END
+
+# various
+MESSAGE MSG_OPEN_FAIL
+Cannot open %s file:
+%s:%s
+#NOHELP
+END
+
+# various
+MESSAGE MSG_BAD_OPTION
+Unrecognized Option: %s
+#NOHELP
+END
+
+# various
+MESSAGE MSG_CARIMP_EOL
+End-Of-Line is unexpected in a quoted field.
+%s
+
+Do you want to continue reading the file?
+#NOHELP
+END
+
+# various
+MESSAGE MSG_CARIMP_MISSING_COMMA
+A comma was expected after this quoted field.
+%s
+
+Do you want to continue reading the file?
+#NOHELP
+END
+
+# various
+MESSAGE MSG_WRITE_FAILURE
+Error \\"%s\\" occurred while writing %s.
+Please check disk space and system status.
+#NOHELP
+END
+
+
+
+############################################################
+# Various messages without help. Sorted by module.
+############################################################
+
+# cgroup.c:doGroup
+MESSAGE MSG_CANT_GROUP_BUMPER2
+At least one path for the Turnout T%d does not
+terminate on an endpoint. Such a track cannot be grouped.
+The track has been unselected.
+#NOHELP
+END
+
+
+
+# cprofile
+MESSAGE MSG_INV_PET_ON_PATH
+inv-pathEndTrk on Path.
+#NOHELP
+END
+
+# cprofile
+MESSAGE MSG_INV_PST_ON_PATH
+inv-pathStartTrk on Path
+#NOHELP
+END
+
+# cprofile
+MESSAGE MSG_PASSERT
+%s:%d- %s
+#NOHELP
+END
+
+# cprofile
+MESSAGE MSG_PET_NOT_ON_PATH
+pathEndTrk not on Path.
+#NOHELP
+END
+
+# cprofile
+MESSAGE MSG_PST_NOT_ON_PATH
+pathStartTrk not on Path.
+#NOHELP
+END
+
+
+
+# cpull.c
+MESSAGE MSG_PULL_ERROR_1
+The tracks cannot be connected together.
+
+Try changing some tracks for a closer fit
+or increase the Connection Angle value on
+the Preferences dialog.
+#NOHELP
+END
+
+# cpull.c
+MESSAGE MSG_PULL_ERROR_2
+The tracks cannot be connected together.
+
+Try changing some tracks for a closer fit
+or increase the Connection Distance and
+Angle values on the Preferences dialog
+#NOHELP
+END
+
+# cpull.c
+MESSAGE MSG_PULL_ERROR_3
+The tracks cannot be connected together.
+
+Try changing some tracks for a closer fit
+or increase the Connection Distance
+#NOHELP
+END
+
+
+
+#cselect.c: cmdRotate
+MESSAGE MSG_1ST_TRACK_MUST_BE_SELECTED
+The first track for the Align
+Rotate command must be Selected.
+END
+
+#cselect.c: cmdRotate
+MESSAGE MSG_2ND_TRACK_MUST_BE_UNSELECTED
+The second track for the Align
+Rotate command must be Unselected.
+END
+
+# cselect.c
+MESSAGE MSG_TOO_MANY_SEL_TRKS
+Too many selected tracks, drawing tracks as End Point.
+#NOHELP
+END
+
+
+
+# csplit.c
+MESSAGE MSG_BAD_BLOCKGAP
+Select an endpoint between two tracks.
+#NOHELP
+END
+
+
+
+# ctodesgn.c
+MESSAGE MSG_TODSGN_NO_CONVERGE
+According to values that have been entered the diverging
+track does not connect with the tangent track. Please
+check the values entered and try again. Check the angle
+is entered as a frog number or in degrees as specified
+by Angle Mode radio buttons.
+#NOHELP
+END
+
+
+
+# cturnout.c:moveEndPtTurnout
+MESSAGE MSG_MOVED_BEFORE_END_TURNOUT
+Moved before the end of the turnout
+#NOHELP
+END
+
+
+
+# dcar.c
+MESSAGE MSG_CARDESC_BAD_COUPLER_LENGTH_VALUE
+The Coupled Length must be greater than the Car Length,
+and the Coupler Length must be greater than 0.
+END
+
+# dcar.c
+MESSAGE MSG_CARDESC_BAD_DIM_VALUE
+The Car Length value must be greater
+than the Car Width value.
+END
+
+# dcar.c
+MESSAGE MSG_CARITEM_BAD_INDEX
+The specified Index is already in use.
+The Index will be updated to the next available value.
+END
+
+#dcar.c
+MESSAGE MSG_CARDESC_CHANGED
+You have changed values for this object.
+
+Are you sure you want to Close?
+END
+
+
+
+# fileio.c
+MESSAGE MSG_BAD_FILE_VERSION
+File version %ld is lower than the minimum
+supported version %d. You need to update your
+layout file using an older version of %s
+#NOHELP
+END
+
+
+
+# macro.c
+MESSAGE MSG_CANT_READ_DEMO
+%s cannot read the demo file:
+%s
+#NOHELP
+END
+
+#macro.c
+MESSAGE MSG_DEMO_BAD_NUM
+doDemo: bad number (%d)
+#NOHELP
+END
+
+# macro.c
+MESSAGE MSG_PLAYBACK_TIMEEND
+Playback TIMEEND without TIMESTART
+#NOHELP
+END
+
+#macro.c
+MESSAGE MSG_PLAYBACK_UNK_CMD
+Unknown playback command (%d)
+%s
+#NOHELP
+END
+
+# macro.c
+MESSAGE MSG_PLAYBACK_VERSION_DOWNGRADE
+Playback file version %ld is lower than the
+minimum supported version %d.
+You need to update your layout file using an
+older version of %s
+#NOHELP
+END
+
+# misc2.c
+MESSAGE MSG_BAD_SCALE_INDEX
+Scale index (%d) is not valid
+#NOHELP
+END
+
+# misc2.c
+MESSAGE MSG_BAD_SCALE_NAME
+Scale %s is not valid
+Please check your %s.xtq file
+#NOHELP
+END
+
+
+
+# tcurve.c
+MESSAGE MSG_CANT_EXTEND_HELIX
+Cannot extend a helix
+#NOHELP
+END
+
+# tcurve.c
+MESSAGE MSG_CANT_TRIM_HELIX
+Cannot trim a helix
+#NOHELP
+END
+
+
+
+# track.c: auditPrint
+MESSAGE MSG_AUDIT_PRINT_IGNORE
+Ignore further audit notices?
+#NOHELP
+END
+
+# track.c: auditPrint
+MESSAGE MSG_AUDIT_PRINT_MSG
+%s
+#NOHELP
+END
+
+# track.c: auditTracks
+MESSAGE MSG_AUDIT_ABORT
+Audit Abort?
+#NOHELP
+END
+
+# track.c: auditTracks
+MESSAGE MSG_AUDIT_WRITE_FILE
+Write Audit File?
+#NOHELP
+END
+
+# track.c:checkTrackLength
+MESSAGE MSG_CTL_SHORT_TRK
+checkTrackLength: Short track length = %0.3f
+#NOHELP
+END
+
+# track.c:checkTrackLength
+MESSAGE MSG_CTL_UNK_TYPE
+checkTrackLength: unknown type: %d
+#NOHELP
+END
+
+# track.c: connectTracks
+MESSAGE MSG_CONNECT_TRK
+connectTracks: T%d[%d] T%d[%d] d=%0.3f a=%0.3f
+#NOHELP
+END
+
+# track.c: getAngleAtPoint
+MESSAGE MSG_GAAP_BAD_TYPE
+GetAngleAtPoint: bad type(%d) for T(%d)
+END
+
+# track.c
+MESSAGE MSG_MEP_INV_TRK
+joinTracks: invalid track type=%d
+#NOHELP
+END
+
+# track.c: resolveIndex
+MESSAGE MSG_RESOLV_INDEX_BAD_TRK
+resolveIndex: T%d[%d]: T%d doesn\\'t exist
+#NOHELP
+END
+
+
+
+# tstraigh.c:moveEndPtStraight
+MESSAGE MSG_MOVED_BEYOND_END_TRK
+Moved beyond the end of the track
+#NOHELP
+END
+
+
+
+
+
+
+############################################################
+# Message Archive
+############################################################
+
+#MESSAGE MSG_CANT_MODIFY_THAT
+#Cannot modify that
+#HELP
+#helptext
+#END
+
+#MESSAGE MSG_JOIN_TRK
+#Cannot join to %s object
+#ALT
+#Cannot join to First|Second object
+#HELP
+#Not possible
+#END
+
+#MESSAGE MSG_CANT_EXTEND
+#Cannot extend non-track object
+#HELP
+#Not possible.
+#You can only $XExtend|cmdModify$ Track objects, not Lines or TableEdges.
+#You can $XModify|cmdModify$ these objects, or select a Track object $XModify|cmdModify$.
+#END
+
+#MESSAGE MSG_INV_TRK_PARALLEL
+#Invalid track for parallel
+#HELP
+#helptext
+#END
+
+#MESSAGE MSG_INVALID_TRK
+#Invalid Track
+#HELP
+#helptext
+#END
+
+#MESSAGE MSG_JOIN_STRAIGHT_STRAIGHT
+#Cannot join a straight joint to a straight track
+#HELP
+#
+#END
+
+# cjoin.c ifdef'd out
+#MESSAGE MSG_NO_ENDPTS
+#Object has no endpoints
+#HELP
+#helptext
+#END
+
+#MESSAGE MSG_SEL_EP_CONN
+#Selected track endpoint is connected
+#HELP
+#helptext
+#END
+
+# cprint.c
+# MESSAGE MSG_PRINT_SCALE_1
+# Print Scale cannot be 1 in the unregistered version of %s
+# ALT
+# Print Scale cannot be 1 in the unregistered version of XTrkCad
+# HELP
+# The unregistered version of this program cannot print full size (1:1). To register the program see the $Xon-line help|registration$.
+# END
+
+# cprofile:profileSelect ifdef'd out
+#MESSAGE MSG_EP_NOT_DEP
+#Endpoint is not a defined elevation
+#HELP
+#helptext
+#END
+
+# cprofile.c: profileDefine ifdef'f out
+#MESSAGE MSG_EP_ELEV_DEFINED
+#Endpoint Elevation is already defined
+#HELP
+#helptext
+#END
+
+# cprofile.c
+#MESSAGE MSG_IGNORE_DEP
+#Cannot Ignore a Defined Elevation endpoint
+#HELP
+#helptext
+#END
+
+#MESSAGE MSG_CARINV_CHANGESCALE
+#Editing this Car Item will change it's scale.
+#Do you want to continue?
+#HELP
+#The Scale for each Car Item is set by the active Scale
+#when it is created or edited.
+#The active Scale is set on the $XLayout|cmdLayout$ dialog.
+#The Car Item you have selected has a different Scale then
+#the active Scale and it will be changed when edited.
+#END
+
+# MESSAGE MSG_CARINV_TOOMANYCARS
+# The unregistered version of this program is restricted to less than 50 tracks and cars.
+# END
+
+# doption.c
+# MESSAGE MSG_SETUP_ROOMSIZE
+# Room size greater than 96\\" x 48\\" only available with Level 1
+# HELP
+# Unregistered versions of this program are limited to a maximum Room Size of 96" by 48". To register the program see the $Xon-line help|registration$.
+# END
diff --git a/app/help/mkpngbutt b/app/help/mkpngbutt
new file mode 100755
index 0000000..0b77831
--- /dev/null
+++ b/app/help/mkpngbutt
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+
+NAME=$1
+shift
+FILES=""
+for F in $* ; do
+ FILES="${FILES} ../bin/$F.xpm"
+done
+#echo ${NAME}
+
+(./mkxpmbutt ${NAME} ${FILES} | convert +compress XPM:- PNG:temp.png) 2>&1
+#(./mkxpmbutt ${NAME} ${FILES} | convert +compress -transparency '#111' XPM:- PNG:temp.png) 2>&1
+#(./mkxpmbutt ${NAME} ${FILES} | xpmtoppm | pnmtopng -force > temp.png) 2>&1
+#(mkxpmbutt ${NAME} ${FILES} | convert -transparency '#111' XPM:- PNG:temp.png) 2>&1
+if cmp -s temp.png png.d/${NAME}.png ; then
+ rm temp.png
+else
+ echo updating ${NAME}.png
+ mv temp.png png.d/${NAME}.png
+fi
diff --git a/app/help/mkpngs b/app/help/mkpngs
new file mode 100755
index 0000000..a230ea4
--- /dev/null
+++ b/app/help/mkpngs
@@ -0,0 +1,88 @@
+#!/bin/sh
+./mkpngbutt bzoomin zoomin
+./mkpngbutt bzoom zoom
+./mkpngbutt bzoomout zoomout
+./mkpngbutt bgzoom zoomin zoom zoomout
+
+./mkpngbutt bundo undo
+./mkpngbutt bredo redo
+./mkpngbutt bgundo undo redo
+
+./mkpngbutt bease enone
+./mkpngbutt bgease enone
+
+./mkpngbutt bgsnap snapcurs snapvis
+
+./mkpngbutt bstraigh straight
+./mkpngbutt bcurve curve1 openbutt
+./mkpngbutt bcircle circle1 openbutt
+./mkpngbutt bhelix helix
+./mkpngbutt bturnout turnout
+./mkpngbutt bhndldto hndldto
+./mkpngbutt bturntbl turntbl
+./mkpngbutt bparalle parallel
+./mkpngbutt bgtrkcrt straight curve1 openbutt circle1 openbutt helix turnout hndldto turntbl parallel
+
+./mkpngbutt bcurve1 curve1
+./mkpngbutt bcurve2 curve2
+./mkpngbutt bcurve3 curve3
+./mkpngbutt bcurve4 curve4
+./mkpngbutt bcircl1 circle1
+./mkpngbutt bcircl2 circle2
+./mkpngbutt bcircl3 circle3
+
+./mkpngbutt bmodify extend
+./mkpngbutt bjoin join
+./mkpngbutt bconnect pull
+./mkpngbutt bsplit splittrk
+./mkpngbutt belev elev
+./mkpngbutt bprofile profile
+./mkpngbutt bmovedes movedesc
+./mkpngbutt bgtrkmod extend join pull splittrk elev profile movedesc
+
+./mkpngbutt bdescrib describe
+./mkpngbutt bselect select
+./mkpngbutt bgselect describe select
+
+./mkpngbutt bmove move
+./mkpngbutt brotate rotate
+./mkpngbutt bflip flip
+./mkpngbutt bdelete delete
+./mkpngbutt btunnel tunnel
+./mkpngbutt babove above
+./mkpngbutt bbelow below
+./mkpngbutt babvbel above below
+./mkpngbutt bgtrkgrp move rotate flip delete tunnel above below
+
+./mkpngbutt btext text
+./mkpngbutt bdraw dline openbutt dcurve1 openbutt dcircle1 openbutt dbox openbutt
+./mkpngbutt bnote cnote
+./mkpngbutt bstruct struct
+./mkpngbutt bgmsccrt text dline dcurve1 openbutt dcircle1 openbutt dbox openbutt cnote struct
+
+./mkpngbutt dline dline
+./mkpngbutt ddimlin ddimlin
+./mkpngbutt dbench dbench
+./mkpngbutt dtbledge dtbledge
+./mkpngbutt dcurve1 dcurve1
+./mkpngbutt dcurve2 dcurve2
+./mkpngbutt dcurve3 dcurve3
+./mkpngbutt dcurve4 dcurve4
+./mkpngbutt dcircle2 dcircle2
+./mkpngbutt dcircle3 dcircle3
+./mkpngbutt dflcrcl2 dflcrcl2
+./mkpngbutt dflcrcl3 dflcrcl3
+./mkpngbutt dbox dbox
+./mkpngbutt dfilbox dfilbox
+./mkpngbutt dpoly dpoly
+./mkpngbutt dfilpoly dfilpoly
+
+
+./mkpngbutt bruler ruler
+./mkpngbutt bgruler ruler
+
+./mkpngbutt btrain train
+./mkpngbutt bgtrain train
+./mkpngbutt bnewcar newcar
+
+exit 0
diff --git a/app/help/mkshg.c b/app/help/mkshg.c
new file mode 100644
index 0000000..4c708fa
--- /dev/null
+++ b/app/help/mkshg.c
@@ -0,0 +1,455 @@
+#include <stdio.h>
+#include <string.h>
+#include "readpng.h"
+
+#define PROGNAME "mkshg"
+
+
+int verbose = 0;
+int dmpcolortab = 0;
+int dmpimage = 0;
+
+#define MAXRUNLEN (2)
+
+typedef struct {
+ unsigned char id0, id1, id2;
+ unsigned short x, y, w, h;
+ long hash;
+ char * name;
+ char * context;
+ } hotspot_t;
+
+int samecolor( long color1, long color2 )
+{
+ long c1, c2;
+ int i;
+ for ( i=0; i<3; i++ ) {
+ c1 = (color1&0xFF);
+ c2 = (color2&0xFF);
+ if ( c1 != c2 ) {
+ if ( c1 == 0xFF || c2 == 0xFF ) return FALSE;
+ c1 = (c1+1)&0xFE;
+ c2 = (c2+1)&0xFE;
+ if ( c1 != c2 ) return FALSE;
+ }
+ color1 >>= 8;
+ color2 >>= 8;
+ }
+ return TRUE;
+}
+
+void conv24to8( long * colorTab, char * buff, unsigned long channels, unsigned long width24, unsigned long width8, unsigned long height )
+{
+ long * lastColor, *cp;
+ long color;
+ char * ip;
+ char *op;
+ unsigned long h, w;
+ memset( colorTab, 0, 1024 );
+ lastColor = colorTab;
+ *lastColor++ = 0xC0C0C0;
+ *lastColor++ = 0xFFFFFF;
+ *lastColor++ = 0x808080;
+ *lastColor++ = 0x000000;
+ op = buff;
+ for (h=0; h<height; h++) {
+ ip = buff+(width24*h);
+ op = buff+(width8*h);
+ for (w=0; w<width24; w+=channels,op++ ) {
+ color = ((long)(unsigned char)(ip[0]))<<16;
+ color += ((long)(unsigned char)(ip[1]))<<8;
+ color += ((long)(unsigned char)(ip[2]));
+ ip += channels;
+ for ( cp=colorTab; cp<lastColor; cp++ ) {
+ if ( samecolor( color, *cp ) ) {
+ *op = (char)(cp-colorTab);
+ goto nextPixel;
+ }
+ }
+ if (lastColor < &colorTab[256]) {
+ *op = (char)(lastColor-colorTab);
+ *lastColor++ = color;
+ } else {
+ *op = 0;
+ }
+nextPixel:
+ if ( dmpimage ) {
+ char c;
+ if ( *op < 10 )
+ printf( "%c", '0'+*op );
+ else if ( *op < 10+26 )
+ printf( "%c", *op-10+'a' );
+ else if ( *op < 10+26+26 )
+ printf( "%c", *op-10-26+'A' );
+ else
+ printf( "\%2.2x", *op );
+ }
+ }
+ *op++ = 0;
+ *op++ = 0;
+ if ( dmpimage )
+ printf( "00\n" );
+ }
+if ( dmpcolortab ) {
+ int i;
+ for ( i=0; i<lastColor-colorTab; i++ ) {
+ printf( "C[%3d] %6.6lx\n", i, colorTab[i] );
+ }
+}
+}
+
+
+void compress_data(
+ unsigned char * ip0,
+ unsigned long isize,
+ unsigned char * op0,
+ unsigned long * osize )
+{
+ unsigned char * ip=ip0, * op=op0;
+ int runlen, norunlen, chunk;
+ norunlen = 0;
+ while ( ip < ip0+isize ) {
+ for ( runlen=0; ip+runlen<ip0+isize && ip[0]==ip[runlen]; runlen++ );
+ if ( runlen > MAXRUNLEN || runlen == 0 ) {
+ while ( norunlen > 0 ) {
+ if ( norunlen > 0x7F )
+ chunk = 0x7F;
+ else
+ chunk = norunlen;
+ *op++ = 0x80|chunk;
+ memcpy( op, ip-norunlen, chunk );
+ op += chunk;
+ norunlen -= chunk;
+ }
+ while ( runlen > MAXRUNLEN ) {
+ if ( runlen > 0x7F )
+ chunk = 0x7F;
+ else
+ chunk = runlen;
+ *op++ = chunk;
+ *op++ = *ip;
+ ip += chunk;
+ runlen -= chunk;
+ }
+ } else {
+ norunlen += runlen;
+ ip += runlen;
+ }
+ }
+ *osize = op-op0;
+}
+
+
+void writeculong( FILE * shgF, unsigned long value )
+{
+ unsigned short tmp;
+ if ( value > 0x7FFF ) {
+ tmp = (unsigned short)((value&0x7FFF)<<1)+1;
+ fwrite( &tmp, 2, 1, shgF );
+ tmp = (unsigned short)(value>>15);
+ fwrite( &tmp, 2, 1, shgF );
+ } else {
+ tmp = (unsigned short)(value<<1);
+ fwrite( &tmp, 2, 1, shgF );
+ }
+}
+
+void writecushort( FILE * shgF, unsigned short value )
+{
+ unsigned char tmp;
+ if ( value > 0x7F ) {
+ tmp = (unsigned short)((value&0x7F)<<1)+1;
+ fwrite( &tmp, 1, 1, shgF );
+ tmp = (unsigned short)(value>>7);
+ fwrite( &tmp, 1, 1, shgF );
+ } else {
+ tmp = (unsigned short)(value<<1);
+ fwrite( &tmp, 1, 1, shgF );
+ }
+}
+
+void writeShgPic(
+ FILE * shgF,
+ unsigned long width,
+ unsigned long width8,
+ unsigned long height,
+ long colorTab[256],
+ unsigned char * data,
+ unsigned short hotspotcnt,
+ hotspot_t * hotspots )
+{
+ short int pictype, packmethod;
+ unsigned long xdpi, ydpi, colorsused, colorsimportant, compressedsize, hotspotsize, compressoffset, hotspotoffset;
+ unsigned short planes, bitcount;
+ unsigned char * compressed_data;
+ unsigned int start_off, offset_off, off;
+ unsigned short inx;
+ unsigned char one = 1;
+ unsigned long macrosize = 0;
+
+ pictype = 6;
+ packmethod = 1;
+ xdpi = ydpi = 96;
+ planes = 1;
+ bitcount = 8;
+ colorsused = 256;
+ colorsimportant = 256;
+ hotspotsize = (hotspotcnt?7:0);
+ hotspotoffset = 0;
+ compressed_data = (unsigned char *)malloc( width8*height );
+ compress_data( data, width8*height, compressed_data, &compressedsize );
+ for ( inx=0; inx<hotspotcnt; inx++ )
+ hotspotsize += 15+strlen(hotspots[inx].name)+1+strlen(hotspots[inx].context)+1;
+
+ start_off = ftell( shgF );
+ fwrite( &pictype, 1, 1, shgF );
+ fwrite( &packmethod, 1, 1, shgF );
+ writeculong( shgF, xdpi );
+ writeculong( shgF, ydpi );
+ writecushort( shgF, planes );
+ writecushort( shgF, bitcount );
+ writeculong( shgF, width );
+ writeculong( shgF, height );
+ writeculong( shgF, colorsused );
+ writeculong( shgF, colorsimportant );
+ writeculong( shgF, compressedsize );
+ writeculong( shgF, hotspotsize );
+ offset_off = ftell( shgF );
+ compressoffset = offset_off-start_off+8+colorsused*4;
+ fwrite( &compressoffset, 4, 1, shgF );
+ fwrite( &hotspotoffset, 4, 1, shgF );
+ if ( verbose )
+ printf( "TY=%d, PK=%d, XD=%ld, YD=%ld, PL=%d, BC=%d, W=%ld, H=%ld, CU=%ld, CI=%ld, CS=%ld, HS=%ld, CO=%ld, HO=%ld\n",
+ pictype, packmethod, xdpi, ydpi, planes, bitcount, width, height, colorsused, colorsimportant, compressedsize, hotspotsize, compressoffset, hotspotoffset );
+ fwrite( colorTab, colorsused, 4, shgF );
+ fwrite( compressed_data, compressedsize, 1, shgF );
+ if ( hotspotcnt>0 ) {
+ hotspotoffset = ftell( shgF ) - start_off;
+ fwrite( &one, 1, 1, shgF );
+ fwrite( &hotspotcnt, 2, 1, shgF );
+ fwrite( &macrosize, 4, 1, shgF );
+ for ( inx=0; inx<hotspotcnt; inx++ ) {
+ fwrite( &hotspots[inx].id0, 1, 1, shgF );
+ fwrite( &hotspots[inx].id1, 1, 1, shgF );
+ fwrite( &hotspots[inx].id2, 1, 1, shgF );
+ fwrite( &hotspots[inx].x, 2, 1, shgF );
+ fwrite( &hotspots[inx].y, 2, 1, shgF );
+ fwrite( &hotspots[inx].w, 2, 1, shgF );
+ fwrite( &hotspots[inx].h, 2, 1, shgF );
+ fwrite( &hotspots[inx].hash, 4, 1, shgF );
+ }
+ for ( inx=0; inx<hotspotcnt; inx++ ) {
+ fwrite( hotspots[inx].name, strlen(hotspots[inx].name)+1, 1, shgF );
+ fwrite( hotspots[inx].context, strlen(hotspots[inx].context)+1, 1, shgF );
+ }
+ fseek( shgF, offset_off+4, SEEK_SET );
+ fwrite( &hotspotoffset, 4, 1, shgF );
+ }
+
+ free( compressed_data );
+}
+
+
+signed char hashTable[256]=
+{
+ '\x00', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7',
+ '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF',
+ '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
+ '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF',
+ '\xF0', '\x0B', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7',
+ '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\x0C', '\xFF',
+ '\x0A', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0D',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2A', '\x2B', '\x2C', '\x2D', '\x2E', '\x2F',
+ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
+ '\x58', '\x59', '\x5A', '\x5B', '\x5C', '\x5D', '\x5E', '\x5F',
+ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
+ '\x68', '\x69', '\x6A', '\x6B', '\x6C', '\x6D', '\x6E', '\x6F',
+ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
+ '\x78', '\x79', '\x7A', '\x7B', '\x7C', '\x7D', '\x7E', '\x7F',
+ '\x80', '\x81', '\x82', '\x83', '\x0B', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9A', '\x9B', '\x9C', '\x9D', '\x9E', '\x9F',
+ '\xA0', '\xA1', '\xA2', '\xA3', '\xA4', '\xA5', '\xA6', '\xA7',
+ '\xA8', '\xA9', '\xAA', '\xAB', '\xAC', '\xAD', '\xAE', '\xAF',
+ '\xB0', '\xB1', '\xB2', '\xB3', '\xB4', '\xB5', '\xB6', '\xB7',
+ '\xB8', '\xB9', '\xBA', '\xBB', '\xBC', '\xBD', '\xBE', '\xBF',
+ '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
+ '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF'
+};
+
+void readHotspots(
+ FILE * inF,
+ unsigned short * hotspotcnt,
+ hotspot_t * * hotspotptr )
+{
+ hotspot_t hs, *hs_p;
+ int x, y;
+ unsigned short hs_c;
+ char type[80];
+ char name[80];
+ char line[256], *context;
+ int off;
+ int rc;
+
+ hs_c = 0;
+ hs_p = NULL;
+ while ( fgets( line, sizeof line, inF ) != NULL ) {
+ rc=sscanf( line, "%s %hd %hd %hd %hd %n", type, &x, &y, &hs.w, &hs.h, &off );
+ if ( hs_c > 0 ) {
+ if ( x < 0 )
+ x = ((int)hs_p[hs_c-1].x) - x;
+ if ( y < 0 )
+ y = ((int)hs_p[hs_c-1].y) - y;
+ }
+ hs.x = (unsigned short)x;
+ hs.y = (unsigned short)y;
+ if ( rc != 5 )
+ fprintf( stderr, "Invalid hotspot syntax: %s", line );
+ if ( strcasecmp( type, "jump" ) == 0 ) {
+ hs.id0 = 0xe7;
+ hs.id1 = 0x04;
+ hs.id2 = 0x00;
+ } else if ( strcasecmp( type, "popup" ) == 0 ) {
+ hs.id0 = 0xe6;
+ hs.id1 = 0x04;
+ hs.id2 = 0x00;
+ } else if ( strcasecmp( type, "ignore" ) == 0 ) {
+ continue;
+ } else {
+ fprintf( stderr, "Invalid hotspot type: %s", line );
+ continue;
+ }
+ sprintf( name, "Hotspot %d", hs_c+1 );
+ hs.name = strdup( name );
+ context = line+off;
+ off = strlen( context );
+ if ( context[off-1] == '\n' ) context[off-1] = 0;
+ hs.context = strdup( context );
+ for (hs.hash=0; *context; context++ )
+ hs.hash = (hs.hash*43)+hashTable[(unsigned char)*context];
+ hs_c++;
+ hs_p = (hotspot_t*)realloc( hs_p, hs_c * sizeof hs );
+ hs_p[hs_c-1] = hs;
+ }
+ *hotspotcnt = hs_c;
+ *hotspotptr = hs_p;
+}
+
+
+void PngToShg(
+ char * pngFile,
+ char * shgFile )
+{
+ FILE * pngF, * shgF;
+ int rc;
+ unsigned long image_width, image_height, image_rowbytes, width8, h;
+ int image_channels;
+ unsigned char * image_data;
+ double display_exponent = 1.0;
+
+ long size, fileSize, maxRecSize;
+ long colorTab[256];
+
+ short int magic;
+ short int piccnt;
+ long int picoff[1];
+
+ unsigned short hotspotcnt;
+ hotspot_t * hotspotptr;
+
+ pngF = fopen( pngFile, "r" );
+ if ( pngF == NULL ) {
+ perror( pngFile );
+ return;
+ }
+ shgF = fopen( shgFile, "w" );
+ if ( shgF == NULL ) {
+ perror( shgFile );
+ return;
+ }
+ if ((rc = readpng_init(pngF, &image_width, &image_height)) != 0) {
+ switch (rc) {
+ case 1:
+ fprintf(stderr, PROGNAME
+ ": [%s] is not a PNG file: incorrect signature\n",
+ pngFile);
+ break;
+ case 2:
+ fprintf(stderr, PROGNAME
+ ": [%s] has bad IHDR (libpng longjmp)\n",
+ pngFile);
+ break;
+ case 4:
+ fprintf(stderr, PROGNAME ": insufficient memory\n");
+ break;
+ default:
+ fprintf(stderr, PROGNAME
+ ": unknown readpng_init() error\n");
+ break;
+ }
+ return;
+ }
+
+ image_data = readpng_get_image(display_exponent, &image_channels, &image_rowbytes);
+ width8 = ((image_width+3)/4)*4;
+ size = width8*image_height;
+ fileSize = (size+1024)/2 + 70;
+ maxRecSize = (size+1024)/2 + 34;
+
+ conv24to8( colorTab, image_data, image_channels, image_width*image_channels, width8, image_height );
+
+ magic = 0x706c;
+ piccnt = 1;
+ picoff[0] = 8;
+ fwrite( &magic, 2, 1, shgF );
+ fwrite( &piccnt, 2, 1, shgF );
+ fwrite( picoff, 4, piccnt, shgF );
+ readHotspots( stdin, &hotspotcnt, &hotspotptr );
+ writeShgPic( shgF, image_width, width8, image_height, colorTab, image_data, hotspotcnt, hotspotptr );
+ if ( hotspotptr )
+ free( hotspotptr );
+
+ readpng_cleanup(FALSE);
+ fclose( pngF );
+ fclose( shgF );
+ free( image_data );
+
+}
+
+int main( argc, argv )
+int argc; char * argv[];
+{
+ while ( argc > 1 && argv[1][0] == '-' ) {
+ switch ( argv[1][1] ) {
+ case 'v':
+ verbose++;
+ break;
+ case 'c':
+ dmpcolortab++;
+ break;
+ case 'i':
+ dmpimage++;
+ break;
+ default:
+ fprintf( stderr, "Unknown option: %s\n", argv[1] );
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+ if ( argc != 3 ) {
+ fprintf( stderr, "Usage: mkshg [-v] [-c] infile.png outfile.shg\n" );
+ exit(1);
+ }
+
+ PngToShg( argv[1], argv[2] );
+}
diff --git a/app/help/mkshgs b/app/help/mkshgs
new file mode 100755
index 0000000..56dadc3
--- /dev/null
+++ b/app/help/mkshgs
@@ -0,0 +1,348 @@
+rm -f xtchelp.d/*.shg
+
+PNG1DIR=png.d
+PNG2DIR=images.orig
+SHGDIR=xtchelp.d
+
+./mkshg ${PNG1DIR}/bgzoom.png ${SHGDIR}/bgzoom.shg << EOF
+jump 0 0 26 26 cmdZoomIn
+jump 26 0 26 26 cmdZoom
+jump 52 0 26 26 cmdZoomOut
+EOF
+./mkshg ${PNG1DIR}/bgundo.png ${SHGDIR}/bgundo.shg << EOF
+jump 0 0 26 26 cmdUndo
+jump 26 0 26 26 cmdRedo
+EOF
+./mkshg ${PNG1DIR}/bgease.png ${SHGDIR}/bgease.shg << EOF
+jump 0 0 50 25 cmdEasement
+EOF
+./mkshg ${PNG1DIR}/bgsnap.png ${SHGDIR}/bgsnap.shg << EOF
+jump 0 0 26 26 cmdGridEnable
+jump 26 0 26 26 cmdGridShow
+EOF
+./mkshg ${PNG1DIR}/bgtrkcrt.png ${SHGDIR}/bgtrkcrt.shg << EOF
+jump 0 0 26 26 cmdStraight
+jump 26 0 40 26 cmdCurve
+jump 66 0 40 26 cmdCircle
+jump 104 0 26 26 cmdHelix
+jump 132 0 26 26 cmdTurnout
+jump 158 0 26 26 cmdHandLaidTurnout
+jump 184 0 26 26 cmdTurntable
+jump 210 0 26 26 cmdParallel
+EOF
+./mkshg ${PNG1DIR}/bgtrkmod.png ${SHGDIR}/bgtrkmod.shg << EOF
+jump 0 0 26 26 cmdModify
+jump 26 0 26 26 cmdJoin
+jump 52 0 26 26 cmdConnect
+jump 78 0 26 26 cmdSplitTrack
+jump 104 0 26 26 cmdElevation
+jump 130 0 26 26 cmdProfile
+jump 156 0 26 26 cmdMoveDesc
+EOF
+./mkshg ${PNG1DIR}/bgselect.png ${SHGDIR}/bgselect.shg << EOF
+jump 0 0 26 26 cmdDescribe
+jump 26 0 26 26 cmdSelect
+EOF
+./mkshg ${PNG1DIR}/bgtrkgrp.png ${SHGDIR}/bgtrkgrp.shg << EOF
+jump 0 0 26 26 cmdMove
+jump 26 0 26 26 cmdRotate
+jump 52 0 26 26 cmdFlip
+jump 78 0 26 26 cmdDelete
+jump 104 0 26 26 cmdTunnel
+jump 130 0 26 26 cmdAbove
+jump 156 0 26 26 cmdBelow
+EOF
+./mkshg ${PNG1DIR}/bgmsccrt.png ${SHGDIR}/bgmsccrt.shg << EOF
+jump 0 0 26 26 cmdText
+jump 26 0 26 26 cmdDraw
+jump 52 0 40 26 cmdDraw
+jump 92 0 40 26 cmdDraw
+jump 132 0 40 26 cmdDraw
+jump 172 0 26 26 cmdNote
+jump 198 0 26 26 cmdStructure
+EOF
+./mkshg ${PNG1DIR}/bgruler.png ${SHGDIR}/bgruler.shg << EOF
+jump 0 0 26 26 cmdRuler
+EOF
+./mkshg ${PNG1DIR}/bgtrain.png ${SHGDIR}/bgtrain.shg << EOF
+jump 0 0 26 26 cmdTrain
+EOF
+
+for png in ${PNG1DIR}/*.png ; do
+ shg=`echo ${png}|sed -e "s/${PNG1DIR}\///" -e 's/\.png//'`
+ shg=${SHGDIR}\/${shg}.shg
+ if [ ! -f $shg ] ; then
+ ./mkshg $png $shg < /dev/null
+ fi
+done
+
+./mkshg ${PNG2DIR}/bglayer.png ${SHGDIR}/bglayer.shg << EOF
+jump 0 0 400 26 cmdLayer
+EOF
+./mkshg ${PNG2DIR}/bhotbar.png ${SHGDIR}/bhotbar.shg << EOF
+popup 1 1 26 26 _hotBarLeft
+popup 517 1 26 26 _hotBarRight
+EOF
+./mkshg ${PNG2DIR}/bitmap.png ${SHGDIR}/bitmap.shg << EOF
+popup 2 83 132 28 _outputbitmap_density
+popup 2 22 132 60 _outputbitmap_toggles
+EOF
+./mkshg ${PNG2DIR}/blayer.png ${SHGDIR}/blayer.shg << EOF
+jump 0 0 400 26 cmdLayer
+EOF
+./mkshg ${PNG2DIR}/carinv.png ${SHGDIR}/carinv.shg << EOF
+popup 7 24 515 24 _carinv_sort1
+popup 550 28 80 20 _carinv_ok
+popup 550 50 80 20 _carinv_edit
+popup 550 73 80 20 _carinv_add
+popup 550 102 80 20 _carinv_delete
+popup 550 132 80 20 _carinv_import
+popup 550 156 80 20 _carinv_export
+popup 550 179 80 20 _carinv_savetext
+EOF
+./mkshg ${PNG2DIR}/caritem.png ${SHGDIR}/caritem.shg << EOF
+popup 7 28 455 24 _carpart_manuf
+popup 7 54 455 24 _carpart_prototype_list
+popup 7 81 455 24 _carpart_partno_list
+popup 7 143 455 24 _carpart_dispmode
+popup 7 176 455 24 _carpart_index
+popup 7 211 154 24 _carpart_purchPrice
+popup 166 211 145 24 _carpart_currPrice
+popup 314 211 162 24 _carpart_condition
+popup 7 244 185 24 _carpart_purchDate
+popup 197 244 185 24 _carpart_serviceDate
+popup 7 278 154 24 _carpart_quantity
+popup 163 278 253 24 _carpart_multinum
+popup 7 309 442 104 _carpart_notes
+popup 491 47 80 20 _carpart_new
+EOF
+./mkshg ${PNG2DIR}/carpart.png ${SHGDIR}/carpart.shg << EOF
+popup 7 28 455 24 _carpart_manuf
+popup 7 54 455 24 _carpart_prototype_list
+popup 7 81 455 24 _carpart_partno
+popup 7 109 455 24 _carpart_desc
+popup 7 173 455 24 _carpart_road
+popup 7 203 168 24 _carpart_repmark
+popup 179 203 140 24 _carpart_number
+popup 324 203 61 24 _carpart_bodycolor
+popup 7 237 192 24 _carpart_carLength
+popup 203 237 265 24 _carpart_carWidth
+popup 7 265 192 24 _carpart_trkCenter
+popup 203 265 265 24 _carpart_cplrMount
+popup 7 291 192 24 _carpart_cpldLen
+popup 203 291 265 24 _carpart_cplrLen
+popup 491 23 80 20 _carpart_ok
+popup 491 47 80 20 _carpart_newproto
+EOF
+./mkshg ${PNG2DIR}/carproto.png ${SHGDIR}/carproto.shg << EOF
+popup 7 28 455 24 _carpart_prototype
+popup 7 54 455 24 _carpart_type
+popup 7 81 455 24 _carpart_isLoco
+popup 115 109 80 24 _carpart_import
+popup 198 109 80 24 _carpart_reset
+popup 298 109 80 24 _carpart_flip
+popup 7 237 192 24 _carpart_carLength
+popup 203 237 265 24 _carpart_carWidth
+popup 7 265 192 24 _carpart_trkCenter
+popup 7 321 457 100 _carpart_canvas
+popup 491 23 80 20 _carpart_ok
+EOF
+./mkshg ${PNG2DIR}/celev.png ${SHGDIR}/celev.shg << EOF
+popup 5 22 92 127 _elev_mode
+popup 100 46 83 27 _elev_value
+popup 100 73 83 17 _elev_computed
+popup 100 90 83 17 _elev_grade
+popup 100 107 203 27 _elev_station
+ignore 192 23 79 19 _elev_ok
+EOF
+./mkshg ${PNG2DIR}/chelix.png ${SHGDIR}/chelix.shg << EOF
+popup 9 25 232 26 _helix_elev
+popup 9 53 232 26 _helix_radius
+popup 9 80 232 26 _helix_turns
+popup 9 106 232 26 _helix_angSep
+popup 9 133 232 26 _helix_grade
+popup 9 160 232 26 _helix_vertSep
+EOF
+#./mkshg ${PNG2DIR}/cnote.png ${SHGDIR}/cnote.shg << EOF
+#popup 4 22 302 152 _note_text
+#ignore 8 22 31 20 _noteMFile
+#EOF
+./mkshg ${PNG2DIR}/cparalle.png ${SHGDIR}/cparalle.shg << EOF
+popup 227 5 245 19 _parallel_separation
+EOF
+./mkshg ${PNG2DIR}/cprofile.png ${SHGDIR}/cprofile.shg << EOF
+ignore 505 24 79 19 _profile_ok
+popup 505 48 80 19 _profile_clear
+popup 506 71 79 20 _profile_print
+popup 5 23 486 221 _profile_canvas
+ignore 3 244 434 22 _profile_message
+EOF
+./mkshg ${PNG2DIR}/custmgm.png ${SHGDIR}/custmgm.shg << EOF
+popup 5 25 397 230 _custmgm_inx
+popup 415 25 80 20 _custmgm_ok
+popup 415 48 80 20 _custmgm_edit
+popup 415 73 80 20 _custmgm_delete
+popup 415 95 80 20 _custmgm_export
+popup 415 126 80 20 _custmgm_new
+EOF
+./mkshg ${PNG2DIR}/dchgelev.png ${SHGDIR}/dchgelev.shg << EOF
+EOF
+./mkshg ${PNG2DIR}/demo.png ${SHGDIR}/demo.shg << EOF
+popup 7 53 419 229 _demo_text
+popup 251 27 138 20 _demo_speed
+popup 169 27 81 20 _demo_quit
+popup 87 27 80 20 _demo_next
+popup 5 27 79 20 _demo_step
+EOF
+./mkshg ${PNG2DIR}/dlayer.png ${SHGDIR}/dlayer.shg << EOF
+popup 9 28 252 26 _layer_layer
+popup 9 57 250 24 _layer_name
+popup 9 81 79 24 _layer_color
+popup 9 107 79 24 _layer_visible
+popup 87 107 79 24 _layer_frozen
+popup 167 107 79 24 _layer_onmap
+popup 9 132 130 24 _layer_object_count
+popup 9 167 266 24 _layer_button_count
+EOF
+./mkshg ${PNG2DIR}/easeex1.png ${SHGDIR}/easeex1.shg << EOF
+EOF
+./mkshg ${PNG2DIR}/easeex2.png ${SHGDIR}/easeex2.shg << EOF
+EOF
+./mkshg ${PNG2DIR}/easew.png ${SHGDIR}/easew.shg << EOF
+popup 19 69 266 20 _easement_radio
+popup 165 43 76 25 _easement_l
+popup 83 45 82 22 _easement_x
+popup 3 45 78 24 _easement_r
+popup 54 21 109 22 _easement_val
+EOF
+./mkshg ${PNG2DIR}/grid.png ${SHGDIR}/grid.shg << EOF
+popup 244 99 77 25 _grid_show
+popup 243 24 101 74 _grid_origx
+popup 3 96 188 21 _grid_horzenable
+popup 2 67 189 26 _grid_horzdivision
+popup 2 37 218 29 _grid_horzspacing
+EOF
+./mkshg ${PNG2DIR}/pricels.png ${SHGDIR}/pricels.shg << EOF
+popup 2 49 404 194 _pricelist_inx
+popup 2 22 404 24 _pricelist_cost
+popup 2 248 404 24 _pricelist_flexcost
+EOF
+./mkshg ${PNG2DIR}/print.png ${SHGDIR}/print.shg << EOF
+popup 5 26 190 25 _print_scale
+popup 5 54 190 25 _print_pagew
+popup 198 54 80 20 _print_max
+popup 5 78 190 25 _print_pageh
+popup 198 78 80 20 _print_snapshot
+popup 5 101 274 25 _print_format
+popup 5 122 274 25 _print_order
+popup 5 156 275 25 _print_style
+popup 5 180 275 25 _print_physsize
+popup 5 205 275 25 _print_registrationMarks
+popup 5 227 275 25 _print_grid
+popup 5 252 275 25 _print_ruler
+popup 5 277 275 25 _print_roadbed
+popup 5 301 275 25 _print_roadbedWidth
+popup 5 333 165 80 _print_origx
+popup 173 362 80 20 _print_reset
+popup 291 23 80 20 _print_ok
+popup 291 47 80 20 _printSetup
+popup 291 68 80 20 _print_clear
+EOF
+./mkshg ${PNG2DIR}/prmfile.png ${SHGDIR}/prmfile.shg << EOF
+popup 392 88 81 20 _prmfile_browse
+popup 393 67 81 18 _prmfile_action
+popup 76 215 150 23 _prmfile_mode
+popup 1 19 371 193 _prmfile_inx
+EOF
+./mkshg ${PNG2DIR}/regw.png ${SHGDIR}/regw.shg << EOF
+popup 1 110 299 26 _parameter_key
+popup 1 81 301 27 _parameter_name
+EOF
+./mkshg ${PNG2DIR}/rescale.png ${SHGDIR}/rescale.shg << EOF
+popup 1 21 274 24 _rescale_toggle
+popup 1 45 142 24 _rescale_from
+popup 143 45 131 24 _rescale_to
+popup 1 72 274 24 _rescale_change_gauge
+popup 1 99 274 24 _rescale_ratio
+popup 283 21 80 24 _rescale_ok
+EOF
+./mkshg ${PNG2DIR}/strsel.png ${SHGDIR}/strsel.shg << EOF
+popup 366 75 87 61 _structure_stats
+popup 9 272 440 220 _structure_canvas
+popup 9 26 350 241 _structure_list
+popup 366 48 80 20 _structure_hide
+EOF
+./mkshg ${PNG2DIR}/ctext.png ${SHGDIR}/ctext.shg << EOF
+popup 223 2 280 24 _text_fontsize
+EOF
+./mkshg ${PNG2DIR}/ttdiam.png ${SHGDIR}/ttdiam.shg << EOF
+popup 224 4 245 19 _turntable_diameter
+EOF
+./mkshg ${PNG2DIR}/turndes.png ${SHGDIR}/turndes.shg << EOF
+popup 494 158 86 42 _turnoutNew_angleMode
+popup 494 70 80 20 _printSetup
+popup 494 44 80 20 _turnoutNew_print
+popup 50 139 135 25 _turnoutNew_len1
+popup 282 87 126 25 _turnoutNew_off1
+popup 357 47 124 25 _turnoutNew_angle1
+popup 126 29 130 25 _turnoutNew_len1
+popup 5 167 478 25 _turnoutNew_manuf
+popup 5 196 343 53 _turnoutNew_desc1
+popup 352 196 129 53 _turnoutNew_partno1
+popup 5 250 200 25 _turnoutNew_roadbedWidth
+popup 209 250 117 25 _turnoutNew_roadbedLineWidth
+popup 328 250 65 25 _turnoutNew_color
+EOF
+./mkshg ${PNG2DIR}/turnsel.png ${SHGDIR}/turnsel.shg << EOF
+popup 10 314 25 25 _turnout_endPoint
+popup 10 277 25 25 _turnout_endPoint
+popup 379 314 25 25 _turnout_endPoint
+popup 379 277 25 25 _turnout_activeEndPoint
+popup 330 49 80 20 _turnout_new
+popup 330 72 80 20 _turnout_hide
+popup 6 269 404 133 _turnout_canvas
+popup 6 26 316 243 _turnout_list
+EOF
+./mkshg ${PNG2DIR}/train.png ${SHGDIR}/train.shg << EOF
+popup 4 23 120 24 _train_list
+popup 4 93 22 200 _train_speed
+popup 27 91 80 24 _train_distance
+popup 112 91 14 24 _train_zeroDistance
+popup 27 129 80 24 _train_goto
+popup 27 160 80 24 _train_follow
+popup 27 183 80 24 _train_autoreverse
+popup 27 213 80 24 _train_direction
+popup 27 244 80 24 _train_stop
+EOF
+./mkshg ${PNG2DIR}/trainbar.png ${SHGDIR}/trainbar.shg << EOF
+EOF
+./mkshg ${PNG2DIR}/updttl.png ${SHGDIR}/updttl.shg << EOF
+popup 1 150 301 21 _updatetitle_old
+popup 4 177 303 196 _updatetitle_sel
+popup 310 177 80 20 _updatetitle_ok
+popup 310 200 80 19 _updatetitle_ignore
+popup 310 223 80 19 _updatetitle_load
+EOF
+./mkshg ${PNG2DIR}/wenum.png ${SHGDIR}/wenum.shg << EOF
+popup 6 26 550 278 _enum_text
+popup 565 26 80 20 _enum_save
+popup 565 50 80 20 _enum_print
+popup 565 74 80 20 _printSetup
+popup 565 100 80 20 _enum_list_prices
+EOF
+./mkshg ${PNG2DIR}/wmain.png ${SHGDIR}/wmain.shg << EOF
+popup 3 25 645 18 _main_menubar
+popup 3 41 645 59 _main_commandbar
+popup 3 102 645 27 _main_layers
+popup 3 136 645 34 _main_hotbar
+popup 3 2 645 21 _main_titlebar
+popup 3 173 645 301 _main_canvas
+popup 7 476 50 22 _infoBarScale
+popup 63 476 49 22 _infoBarCount
+popup 119 476 115 22 _infoBarPosX
+popup 238 476 115 22 _infoBarPosY
+popup 364 476 283 22 _infoBarStatus
+EOF
+./mkshg ${PNG2DIR}/wmap.png ${SHGDIR}/wmap.shg << EOF
+popup 95 349 112 50 _map_hilight
+EOF
diff --git a/app/help/mkxpmbutt.c b/app/help/mkxpmbutt.c
new file mode 100644
index 0000000..4b09a80
--- /dev/null
+++ b/app/help/mkxpmbutt.c
@@ -0,0 +1,303 @@
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ int w;
+ int h;
+ char * b;
+ } bitmap_t;
+
+#define RGB(R,G,B) (((R)<<16)|((G)<<8)|(B))
+
+static struct {
+ long rgb;
+ int key;
+ } mainColorMap[256];
+static int mainColorCnt;
+static int fileColorMap[256];
+
+static int sizeColorMap( void )
+{
+ return mainColorCnt;
+}
+
+static void printColorMap( FILE * fout )
+{
+ int inx, r, g, b;
+ long rgb;
+ for ( inx=0; inx<mainColorCnt; inx++ ) {
+ rgb = mainColorMap[inx].rgb;
+ r = (rgb>>16)&0xFF;
+ g = (rgb>>8)&0xFF;
+ b = (rgb)&0xFF;
+ fprintf( fout, "\"%c\tc #%2.2X%s%2.2X%s%2.2X%s\",\n",
+ mainColorMap[inx].key,
+ r, ((r&1)?"FF":"00"),
+ g, ((g&1)?"FF":"00"),
+ b, ((b&1)?"FF":"00") );
+ }
+}
+
+static int allocColor( long color )
+{
+ int inx;
+ for ( inx=0; inx<mainColorCnt; inx++ ) {
+ if ( mainColorMap[inx].rgb == color )
+ return mainColorMap[inx].key;
+ }
+ if ( mainColorCnt >= 256 ) {
+ fprintf( stderr, "too many colors\n" );
+ exit(1);
+ }
+ mainColorMap[mainColorCnt].rgb = color;
+ mainColorMap[mainColorCnt].key = mainColorCnt+'0';
+ return mainColorMap[mainColorCnt++].key;
+}
+
+static void resetColor( void )
+{
+ int inx;
+ for ( inx=0; inx<256; inx++ )
+ fileColorMap[inx] = -1;
+}
+
+static void mapColor( int inx, long rgb )
+{
+ fileColorMap[inx] = allocColor(rgb);
+}
+
+static int remapColor( int oldColor )
+{
+ int newColor;
+ newColor = fileColorMap[oldColor];
+ if ( newColor < 0 ) {
+ fprintf( stderr, "unknown color inx: %d\n", oldColor );
+ return ' ';
+ }
+ return newColor;
+}
+
+static int read_xpm(
+ char * filename,
+ int *rw,
+ int *rh,
+ int bx,
+ int by,
+ bitmap_t *bm )
+{
+ char line[1024], *cp, *cq, *buffer, color[5];
+ FILE * f;
+ int numcol, curcol, depth, linenum;
+ int col, row, len, r, g, b;
+ long rgb;
+
+ f = fopen( filename, "r" );
+ if ( !f ) {
+ perror( filename );
+ return 0;
+ }
+ numcol = -1;
+ curcol = 0;
+ linenum = 0;
+ resetColor();
+ row = by;
+ while (fgets( line, sizeof line, f ) ) {
+ linenum++;
+ if ( line[0] != '"' )
+ continue;
+ if ( numcol == -1 ) {
+ if ( sscanf( line+1, "%d%d%d%d", rw, rh, &numcol, &depth ) != 4 ) {
+ fprintf( stderr, "bogus XPM header: %s:%d\n", filename, linenum );
+ return 0;
+ }
+ if (!bm)
+ return 1;
+ } else if ( curcol < numcol ) {
+ if ( strncmp( line+2, "\tc #", 4 ) != 0 ) {
+ fprintf( stderr, "bogus XPM color line: %s:%d\n", filename, linenum );
+ return 0;
+ }
+ color[3] = 0;
+ memcpy( color, line+6, 2 );
+ r = strtol( color, &cp, 16 );
+ memcpy( color, line+10, 2 );
+ g = strtol( color, &cp, 16 );
+ memcpy( color, line+14, 2 );
+ b = strtol( color, &cp, 16 );
+ rgb = RGB(r,g,b);
+ if ( curcol == 0 )
+ fileColorMap[line[1]] = '0';
+ else
+ mapColor( line[1], rgb );
+ curcol++;
+ } else {
+ if ( row > by+*rh ) {
+ fprintf( stderr, "too many data lines: %s:%d\n", filename, linenum );
+ return 0;
+ }
+ if ( row > bm->h )
+ return 1;
+ cp = line+1;
+ for ( col=0; col<*rw; col++,cp++ ) {
+ if ( bx+col > bm->w )
+ break;
+ if ( *cp == '"' ) {
+ fprintf( stderr, "short data line: %s:%d\n", filename, linenum );
+ return 0;
+ }
+ bm->b[bx+col+bm->w*row] = remapColor( *cp );
+ }
+ row++;
+ }
+ }
+ fclose( f );
+ return 1;
+}
+
+static void drawVline(
+ bitmap_t * bm,
+ int col,
+ int x,
+ int y0,
+ int y1 )
+{
+ int jj;
+ if ( x > bm->w )
+ return;
+ for ( jj=y0; jj<=y1; jj++ ) {
+ if ( jj>=bm->h )
+ return;
+ bm->b[jj*bm->w+x] = col;
+ }
+}
+
+
+static void drawHline(
+ bitmap_t * bm,
+ int col,
+ int x0,
+ int x1,
+ int y )
+{
+ int ii;
+ if ( y > bm->h )
+ return;
+ for ( ii=x0; ii<=x1; ii++ ) {
+ if ( ii>=bm->w )
+ return;
+ bm->b[y*bm->w+ii] = col;
+ }
+}
+
+static void fillBlock(
+ bitmap_t * bm,
+ int col,
+ int x,
+ int y,
+ int w,
+ int h )
+{
+ int ii, jj;
+ for ( jj=y; jj<y+h; jj++ ) {
+ if ( jj>bm->h )
+ return;
+ for ( ii=x; ii<x+w; ii++ ) {
+ if ( ii>bm->w )
+ return;
+ bm->b[jj*bm->w+ii] = col;
+ }
+ }
+}
+
+
+int main ( int argc, char * argv[] )
+{
+ char * name;
+ int colWhite, colMdGray, colDkGray, colBlack;
+ int bx, w, h;
+ bitmap_t bm;
+ char ** filename;
+ int ii, jj;
+ char * cp;
+ int argn;
+
+ if ( argc < 3 ) {
+ fprintf( stderr, "usage: %s NAME FILE1.XPM...\n", argv[0] );
+ exit(1);
+ }
+
+ colMdGray = allocColor( RGB(0xC0,0xC0,0xC0) );
+ colWhite = allocColor( RGB(255,255,255) );
+ colDkGray = allocColor( RGB(0x80,0x80,0x80) );
+ colBlack = allocColor( RGB(0,0,0) );
+ allocColor( RGB(255,0,0) );
+
+ name = argv[1];
+ argc -= 2;
+ filename = &argv[2];
+
+ bm.w = 1;
+ bm.h = 0;
+ for ( argn=0; argn<argc; argn++ ) {
+ if ( !read_xpm( filename[argn], &w, &h, bx+5, 5, NULL ) )
+ return;
+ if ( h+10 > bm.h )
+ bm.h = h+10;
+ bm.w += w+9;
+ }
+
+ bm.b = (char*)malloc( bm.w*bm.h );
+ memset( bm.b, 0, bm.w*bm.h );
+ fillBlock( &bm, colMdGray, 0, 0, bm.w, bm.h );
+ bx = 0;
+ for ( argn=0; argn<argc; argn++ ) {
+ if ( !read_xpm( filename[argn], &w, &h, bx+5, 5, &bm ) )
+ return;
+ drawVline( &bm, colBlack, bx+0, 0, bm.h-1 );
+ drawVline( &bm, colWhite, bx+1, 1, bm.h-2 );
+ drawVline( &bm, colWhite, bx+2, 1, bm.h-3 );
+ drawVline( &bm, colDkGray, bx+5+w+2, 2, bm.h-2 );
+ drawVline( &bm, colDkGray, bx+5+w+3, 1, bm.h-2 );
+ drawVline( &bm, colBlack, bx+5+w+4, 0, bm.h-1 );
+
+ drawHline( &bm, colBlack, bx+1, bx+5+w+3, 0 );
+ drawHline( &bm, colWhite, bx+1, bx+5+w+2, 1 );
+ drawHline( &bm, colWhite, bx+1, bx+5+w+1, 2 );
+ drawHline( &bm, colDkGray, bx+2, bx+5+w+1, bm.h-3 );
+ drawHline( &bm, colDkGray, bx+1, bx+5+w+1, bm.h-2 );
+ drawHline( &bm, colBlack, bx+1, bx+5+w+3, bm.h-1 );
+
+ bx += w+9;
+ }
+
+ fprintf( stdout, "/* XPM */\n" );
+ fprintf( stdout, "static char * %s_xpm[] = {\n", name );
+ fprintf( stdout, "\"%d %d %d 1\",\n", bm.w, bm.h, sizeColorMap()+1 );
+ fprintf( stdout, "\"Z\tc #000000000000\",\n" );
+ printColorMap( stdout );
+ cp = bm.b;
+ for ( jj=0; jj<bm.h; jj++ ) {
+ fprintf(stdout, "\"%.*s\"%s\n", bm.w, cp, (jj<bm.h-1?",":"};") );
+ cp += bm.w;
+ }
+}
diff --git a/app/help/pageorder.c b/app/help/pageorder.c
new file mode 100644
index 0000000..810e80b
--- /dev/null
+++ b/app/help/pageorder.c
@@ -0,0 +1,48 @@
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#if defined (__sun) && defined (__SVR4)
+#include <stdlib.h>
+#endif
+
+int main ( int argc, char * argv[] ) {
+
+int pagecnt, start, end, count ;
+pagecnt = atoi( argv[1] );
+
+if ( (pagecnt+2)%4 != 0 ) {
+ fprintf( stderr, "pagecnt+2 % 4 != 0\n" );
+ exit(1);
+}
+
+printf( "%d-,%d\n", pagecnt, pagecnt-1 );
+start = 1;
+end = pagecnt-2;
+count=5;
+while ( start < end ) {
+ printf( "%d,%d,%d,%d%s", end,start,start+1,end-1, count>0?",":"\n" );
+ start += 2;
+ end -= 2;
+ count--;
+ if ( count < 0 )
+ count = 5;
+}
+return 0;
+}
diff --git a/app/help/prochelp.c b/app/help/prochelp.c
new file mode 100644
index 0000000..d1dd256
--- /dev/null
+++ b/app/help/prochelp.c
@@ -0,0 +1,2178 @@
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#if defined (__sun) && defined (__SVR4)
+#include <ctype.h>
+#endif
+#include "readpng.h"
+
+#define PROGNAME "prochelp"
+
+char line[1024];
+int lineNum;
+FILE * ifile;
+FILE * ofile;
+int wordwrap = 1;
+int listLevel = -1;
+int listType[10];
+int listCount[10];
+int lineWidth = 80;
+int listWidth = 80;
+int verbose = 0;
+int toc = 0;
+char * dirs[10] = { "." };
+char ** dirList = &dirs[1];
+int FontSize = 22;
+double MarginTop = -1;
+double MarginBottom = -1;
+double MarginLeft = -1;
+double MarginRight = -1;
+double MarginGutter = -1;
+
+#define LISTNONE (0)
+#define LISTBULLET (1)
+#define LISTDASH (2)
+#define LISTNUMBER (3)
+
+int USE_BMP = 0;
+
+
+typedef struct {
+ void (*start)( char *, char * );
+ void (*finish)( void );
+ void (*newParagraph)( void );
+ void (*startLine)( int );
+ void (*doBold)( char * );
+ void (*doItalic)( char * );
+ void (*doXref)( char *, char *, char * );
+ void (*doPicture)( char *, int );
+ void (*endLine)( void );
+ void (*putChar)( char );
+ void (*doSection)( char, char *, char *, char *, char *, int );
+ void (*doHeader)( char * );
+ void (*doStartDisplay)( void );
+ void (*doEndDisplay)( void );
+ void (*doThread)( char * );
+ void (*doListStart)( void );
+ void (*doListItem)( void );
+ void (*doListEnd)( void );
+ void (*page)( void );
+
+ } dispatchTable;
+dispatchTable *curMode;
+
+struct tocList_t;
+typedef struct tocList_t * tocList_p;
+typedef struct tocList_t {
+ tocList_p next;
+ char section;
+ long num;
+ char * title;
+ } tocList_t;
+tocList_p tocHead = NULL;
+tocList_p tocTail = NULL;
+long tocNum = 37061946;
+
+
+void no_op( void )
+{
+}
+FILE * openFile( char * filename )
+{
+ FILE * f;
+ char tmp[1024];
+ char ** d;
+
+ for ( d=dirs; *d; d++ ) {
+ sprintf( tmp, "%s/%s", *d, filename );
+ f = fopen( tmp, "r" );
+ if (f)
+ return f;
+ }
+ fprintf( stderr, "Can't open %s\n", filename );
+ exit(1);
+}
+
+void normalStart( char * inName, char * outName )
+{
+ ifile = openFile( inName );
+ if ( strcmp( outName, "-" ) == 0 ) {
+ ofile = stdout;
+ } else {
+ ofile = fopen( outName, "w" );
+ if (ofile == NULL) {
+ perror( outName );
+ exit( 1 );
+ }
+ }
+}
+void normalFinish( void )
+{
+ if (ofile)
+ fclose( ofile );
+}
+void process( FILE * );
+
+/******************************************************************************
+ *
+ * COMMON RTF
+ *
+ *****************************************************************************/
+
+int rtfNeedPar = FALSE;
+int rtfNeedGap = FALSE;
+int rtfNeedFI0 = FALSE;
+int rtfGapHeight = -1;
+int rtfBigGap = 60;
+
+void rtfFlushParagraph( void )
+{
+ if ( rtfNeedPar ) {
+ if ( rtfNeedGap==TRUE && rtfGapHeight!=rtfBigGap ) {
+ fprintf( ofile, "\\sb%d", rtfBigGap );
+ rtfGapHeight = rtfBigGap;
+ }
+ if ( rtfNeedGap==FALSE && rtfGapHeight!=0 ) {
+ fprintf( ofile, "\\sb0" );
+ rtfGapHeight = 0;
+ }
+ fprintf( ofile, "\\par\n" );
+ if ( rtfNeedFI0 )
+ fprintf( ofile, "\\fi0\n" );
+ rtfNeedPar = FALSE;
+ rtfNeedGap = FALSE;
+ rtfNeedFI0 = FALSE;
+ }
+}
+
+
+void rtfPutChar( char ch )
+{
+ if ( ((ch) & 0x80) ){
+ fprintf( ofile, "\\'%2.2X", (unsigned char)ch );
+ } else if ( (ch) == '\\' ){
+ fprintf( ofile, "\\\\" );
+ } else {
+ fputc( ch, ofile );
+ }
+ rtfNeedPar = TRUE;
+}
+void rtfPutString( char * cp )
+{
+ while (*cp) {
+ rtfPutChar( *cp++ );
+ }
+}
+void rtfNewParagraph( void )
+{
+ if ( wordwrap ) {
+ rtfFlushParagraph();
+#ifdef LATER
+ if ( listLevel < 0 ) {
+ rtfFlushParagraph();
+ rtfNeedGap = 1;
+ } else {
+ if ( rtfNeedPar ) {
+ fprintf( ofile, "\\line\r\n" );
+ rtfNeedPar = FALSE;
+ }
+ }
+#endif
+ }
+}
+void rtfStartLine( int lastBlank )
+{
+ if ( !wordwrap ) {
+ fprintf( ofile, "\\tab\r\n" );
+ } else if ( lastBlank ) {
+ rtfFlushParagraph();
+ }
+}
+void rtfBold( char * name )
+{
+ fprintf( ofile, "{\\b " );
+ rtfPutString( name );
+ fprintf( ofile, "}" );
+}
+void rtfItalic( char * name )
+{
+ fprintf( ofile, "{\\i " );
+ rtfPutString( name );
+ fprintf( ofile, "}" );
+}
+void rtfEndLine( void )
+{
+ if ( !wordwrap ) {
+ rtfNeedPar = TRUE;
+ rtfFlushParagraph();
+ }
+}
+void rtfStartDisplay( void )
+{
+ rtfFlushParagraph();
+}
+void rtfListStart( void )
+{
+ rtfFlushParagraph();
+ if (listLevel>0) {
+ fprintf( ofile, "\\pard" );
+/*
+ if ( rtfNeedGap ) {
+ fprintf( ofile, "\\sb%d", rtfBigGap );
+ rtfGapHeight = rtfBigGap;
+ rtfNeedGap = FALSE;
+ }
+*/
+ rtfGapHeight = -1;
+ }
+ fprintf( ofile, "\\tx360\\li%d\r\n", 360*(listLevel+1) );
+}
+void rtfListItem( void )
+{
+ /*if (listLevel == 0 || listCount[listLevel] > 1)*/
+ rtfFlushParagraph();
+ fprintf( ofile, "\\fi-360 " );
+ rtfNeedFI0 = TRUE;
+ switch (listType[listLevel]) {
+ case LISTNONE:
+#ifdef LATER
+ if ( listCount[listLevel] > 0 )
+ fprintf( ofile, "\\fi-360 " );
+ rtfNeedFI0 = TRUE;
+#endif
+ break;
+ case LISTBULLET:
+ fprintf( ofile, "{\\f1\\'B7}\\tab" );
+ break;
+ case LISTDASH:
+ fprintf( ofile, "{\\b -}\\tab" );
+ break;
+ case LISTNUMBER:
+ fprintf( ofile, "{\\b %d}\\tab", listCount[listLevel] );
+ break;
+ }
+ fprintf( ofile, "\r\n" );
+}
+void rtfListEnd( void )
+{
+ if (listLevel == -1)
+ fprintf( ofile, "\\par\\pard\r\n" );
+ else
+ fprintf( ofile, "\\par\\pard\\tx360\\li%d\\fi-360\r\n", 360*(listLevel+1) );
+ rtfNeedPar = FALSE;
+ rtfGapHeight = -1;
+ rtfNeedGap = FALSE;
+}
+
+void rtfPage( void )
+{
+ rtfFlushParagraph();
+ fprintf( ofile, "\\page\r\n" );
+}
+
+/******************************************************************************
+ *
+ * MSW-HELP
+ *
+ *****************************************************************************/
+
+int pageCnt = 0;
+
+struct {
+ char * name;
+ int count;
+ } threads[100];
+int threadCnt = 0;
+
+
+char * remap_minus( char * cp )
+{
+ char * cp0 = cp;
+ for ( ; *cp; cp++ )
+ if ( *cp == '-' )
+ *cp = '_';
+ return cp0;
+}
+
+int lookupThread( char * name )
+{
+ int inx;
+ if (!name) {
+ fprintf( stderr, "%d: NULL thread string\n", lineNum );
+ return 0;
+ }
+ for (inx=0;inx<threadCnt;inx++) {
+ if (strcmp(threads[inx].name,name)==0) {
+ return ++(threads[inx].count);
+ }
+ }
+ threads[threadCnt].name = strdup( name );
+ threads[threadCnt].count = 1;
+ threadCnt++;
+ return 1;
+}
+
+void mswhelpXref( char * name, char * ref1, char * ref2 )
+{
+ fprintf( ofile, "{\\uldb " );
+ rtfPutString( name );
+ fprintf( ofile, "}{\\v %s}", ref1 );
+}
+void mswhelpPicture( char * name, int inLine )
+{
+ if (inLine) {
+ fprintf( ofile, "\\{bml %s.shg\\}\\tab", name );
+ rtfNeedPar = TRUE;
+ } else {
+ fprintf( ofile, "{\\qc\\{bmc %s.shg\\}\\par\\pard}\r\n", name );
+ rtfNeedPar = FALSE;
+ rtfNeedGap = FALSE;
+ rtfGapHeight = -1;
+ }
+}
+void mswhelpSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ if (pageCnt != 0 && newpage)
+ fprintf( ofile, "\\page\r\n" );
+ pageCnt++;
+ if (context && context[0] != '\0')
+ fprintf( ofile, "#{\\footnote %s}\r\n", remap_minus(context) );
+ if (newpage && title && title[0] != '\0') {
+ fprintf( ofile, "${\\footnote %s}\r\n", title );
+ }
+ if (keywords && keywords[0] != '\0')
+ fprintf( ofile, "K{\\footnote %s}\r\n", keywords );
+ if (picture && picture[0] != '\0') {
+ mswhelpPicture( picture, 1 );
+ }
+ if (title && title[0] != '\0')
+ fprintf( ofile, "{\\b\\fs30 %s}\r\n", title );
+ fprintf( ofile, "\\par\r\n" );
+ rtfNeedPar = FALSE;
+}
+void mswhelpHeader( char * line )
+{
+ if ( line[0] == '*' )
+ return;
+ fprintf( ofile, "#{\\footnote %s}\r\n", remap_minus(line) );
+}
+void mswhelpThread( char * thread )
+{
+ int threadCnt;
+ threadCnt = lookupThread( thread );
+ fprintf( ofile, " +{\\footnote %s:%02d}\r\n", thread, threadCnt );
+}
+dispatchTable mswhelpTable = {
+ normalStart,
+ normalFinish,
+ rtfNewParagraph,
+ rtfStartLine,
+ rtfBold,
+ rtfItalic,
+ mswhelpXref,
+ mswhelpPicture,
+ rtfEndLine,
+ rtfPutChar,
+ mswhelpSection,
+ mswhelpHeader,
+ rtfStartDisplay,
+ (void*)no_op,
+ mswhelpThread,
+ rtfListStart,
+ rtfListItem,
+ rtfListEnd,
+ (void*)no_op
+ };
+
+/******************************************************************************
+ *
+ * MSW-WORD
+ *
+ *****************************************************************************/
+
+
+struct BMFH {
+ char type[2];
+ short size[2];
+ short rsvd1;
+ short rsvd2;
+ short off[2];
+ };
+
+struct BMIH {
+ long size;
+ long width;
+ long height;
+ short planes;
+ short colors;
+ long comp;
+ long imageSize;
+ long xPelsPerMeter;
+ long yPelsPerMeter;
+ long clrUsed;
+ long clrImportant;
+ };
+
+struct BMIH2 {
+ long size;
+ short width;
+ short height;
+ short planes;
+ short colors;
+ };
+
+unsigned short S( short val )
+{
+ union {
+ short inVal;
+ unsigned char outVal[2];
+ } convShort;
+ short ret;
+ convShort.inVal = val;
+ ret = (((short)convShort.outVal[0])<<8) + ((short)convShort.outVal[1]);
+ return ret;
+}
+
+
+long L( long val )
+{
+ union {
+ long inVal;
+ unsigned char outVal[4];
+ } convLong;
+ long ret;
+ convLong.inVal = val;
+ ret = (((long)convLong.outVal[0])<<24) + (((long)convLong.outVal[1])<<16) + (((long)convLong.outVal[2])<<8) + ((long)convLong.outVal[3]);
+ return ret;
+}
+
+
+void dumpBytes( char * buff, long size, FILE * outF )
+{
+ long inx, off, rc;
+ for (inx=0, off=1; inx<size; inx++,off++) {
+ fprintf( outF, "%0.2x", (unsigned char)buff[inx] );
+ if (off >= 40) {
+ fprintf( outF, "\n" );
+ off = 0;
+ }
+ }
+ if (off != 1)
+ fprintf( outF, "\n" );
+}
+
+
+void conv24to8( long * colorTab, unsigned char * buff, int channels, int width24, int width8, int height )
+{
+ long * lastColor, *cp;
+ long color;
+ unsigned char * ip;
+ unsigned char *op;
+ int h, w;
+ lastColor = colorTab;
+ memset( colorTab, 0, 1024 );
+ op = buff;
+ for (h=0; h<height; h++) {
+ ip = buff+(width24*h);
+ op = buff+(width8*h);
+ for (w=0; w<width24; w+=channels,op++ ) {
+ color = ((long)(ip[0]))<<16;
+ color += ((long)(ip[1]))<<8;
+ color += ((long)(ip[2]));
+ ip += channels;
+ for ( cp=colorTab; cp<lastColor; cp++ ) {
+ if (color == *cp) {
+ *op = (unsigned char)(cp-colorTab);
+ goto nextPixel;
+ }
+ }
+ if (lastColor < &colorTab[256]) {
+ *op = (unsigned char)(lastColor-colorTab);
+ *lastColor++ = color;
+ } else {
+ *op = 0;
+ }
+nextPixel:
+ ;
+ }
+ *op++ = 0;
+ *op++ = 0;
+ }
+}
+
+
+void dumpBmp( char * bmpName, FILE * outF )
+{
+ long rc;
+ long size;
+ long fullSize;
+ long scanWidth, width8;
+ long h;
+ long picw, pich;
+ long fileSize, maxRecSize;
+ struct BMFH bmfh;
+ struct BMIH bmih;
+ struct BMIH2 bmih2;
+ char * buff;
+ long * colorTab;
+ long bmfhSize, bmfhOff;
+ FILE * bmpF;
+ int colormapOff;
+ int i, j;
+
+ bmpF = openFile( bmpName );
+ rc = fread( &bmfh, 1, sizeof bmfh, bmpF );
+ rc = fread( &bmih, 1, sizeof bmih, bmpF );
+ colormapOff = sizeof bmfh + sizeof bmih;
+ if (bmih.size == 12L) {
+ fseek( bmpF, sizeof bmfh, SEEK_SET );
+ rc = fread( &bmih2, 1, sizeof bmih2, bmpF );
+ bmih.width = bmih2.width;
+ bmih.height = bmih2.height;
+ bmih.planes = bmih2.planes;
+ bmih.colors = bmih2.colors;
+ bmih.comp = 0;
+ bmih.imageSize = 0;
+ bmih.xPelsPerMeter = 0;
+ bmih.yPelsPerMeter = 0;
+ bmih.clrUsed = 0;
+ bmih.clrImportant = 0;
+ colormapOff = sizeof bmfh + sizeof bmih2;
+ }
+#ifdef LATER
+ bmfh.size = L(bmfh.size);
+ bmfh.off = L(bmfh.off);
+ bmih.size = L(bmih.size);
+ bmih.width = L(bmih.width);
+ bmih.height = L(bmih.height);
+ bmih.planes = S(bmih.planes);
+ bmih.colors = S(bmih.colors);
+ bmih.comp = L(bmih.comp);
+ bmih.imageSize = L(bmih.imageSize);
+ bmih.xPelsPerMeter = L(bmih.xPelsPerMeter);
+ bmih.yPelsPerMeter = L(bmih.yPelsPerMeter);
+ bmih.clrUsed = L(bmih.clrUsed);
+ bmih.clrImportant = L(bmih.clrImportant);
+#endif
+ bmfhSize = ((unsigned short)bmfh.size[0]) + (((long)bmfh.size[1])<<16);
+ bmfhOff = ((unsigned short)bmfh.off[0]) + (((long)bmfh.off[1])<<16);
+ if (verbose) {
+ fprintf( stdout, "BMFH type %c%c, size %ld, off %ld\n",
+ bmfh.type[0], bmfh.type[1], bmfhSize, bmfhOff );
+ fprintf( stdout, "BMIH size %ld, width %ld, height %ld, planes %d, colors %d\n comp %ld, imageSize %ld, xDPM %ld, yDPM %ld, clrUsed %ld, clrImportant %ld\n",
+ bmih.size, bmih.width, bmih.height, bmih.planes, bmih.colors,
+ bmih.comp, bmih.imageSize, bmih.xPelsPerMeter, bmih.yPelsPerMeter,
+ bmih.clrUsed, bmih.clrImportant );
+ }
+ scanWidth = (bmih.width*bmih.colors+7)/8;
+ scanWidth = ((scanWidth+3)/4)*4;
+ fullSize = size = bmfhSize - bmfhOff;
+ if ( fullSize != bmih.height*scanWidth ) {
+ fprintf( stderr, "%s: height*scanWidth(%ld)(%ld) != fullSize(%ld)\n", bmpName, scanWidth, bmih.height*scanWidth, fullSize );
+ return;
+ }
+ if ( bmih.colors != 24 && bmih.colors != 8 && bmih.colors != 4 && bmih.colors != 1) {
+ return;
+ }
+ if ( bmih.planes != 1 ) {
+ fprintf( stderr, "%s: planes(%d) != 1\n", bmpName, bmih.planes );
+ return;
+ }
+ if ( bmih.comp != 0 ) {
+ fprintf( stderr, "%s: comp(%d) != 0\n", bmpName, bmih.comp );
+ return;
+ }
+
+ if (bmih.colors != 8) {
+ size = (((bmih.width+3)/4)*4) * bmih.height;
+ }
+ fileSize = (size+1024)/2 + 70;
+ maxRecSize = (size+1024)/2 + 34;
+
+ picw = bmih.width*26L;
+ pich = bmih.height*26L;
+ if ( outF ) {
+ buff = NULL;
+ fprintf( outF, "{\\pict\\wmetafile8\\picw%ld\\pich%ld\\picwgoal%ld\\pichgoal%ld\\picbmp\\picbpp%d\n",
+ picw, pich, bmih.width*15L, bmih.height*15L, 8/*bmih.colors*/ );
+ fprintf( outF, "010009000003%0.8lx0000%0.8lx0000\n",
+ L(fileSize), L(maxRecSize) );
+ fprintf( outF, "050000000b0200000000\n" ); /* SetWindowOrg(0,0) */
+ fprintf( outF, "050000000c02%0.4x%0.4x\n", S((short)bmih.height), S((short)bmih.width) );
+ fprintf( outF, "05000000090200000000\n" ); /* SetTextColor( 0 ) */
+ fprintf( outF, "050000000102d8d0c800\n" ); /* SetBkColor( 0 ) */
+ fprintf( outF, "0400000007010300\n" ); /* SetStretchBltMode(0300) */
+ fprintf( outF, "%0.8lx430f\n", L(maxRecSize) );
+ fprintf( outF, "2000cc000000%0.4x%0.4x00000000%0.4x%0.4x00000000\n",
+ S((short)bmih.height), S((short)bmih.width), S((short)bmih.height), S((short)bmih.width) );
+ fprintf( outF, "28000000%0.8lx%0.8lx%0.4x%0.4x000000000000000000000000000000000000000000000000\n",
+ L(bmih.width), L(bmih.height), S(bmih.planes), S(8/*bmih.colors*/) );
+ switch ( bmih.colors ) {
+ case 8:
+ buff = (char*)malloc(1024);
+ fseek( bmpF, colormapOff, 0 );
+ rc = fread( buff, 1024, 1, bmpF );
+ if (bmih.size == 12L) {
+ for (h=255; h>=0; h--) {
+ for (i=3; i>=0; i--)
+ buff[h*4+i] = buff[h*3+i];
+ buff[h*4+3] = 0;
+ }
+ }
+ dumpBytes( buff, 1024, outF );
+ rc = fseek( bmpF, bmfhOff, 0 );
+ buff = (char*)realloc( buff, (int)scanWidth );
+ for ( h=0; h<bmih.height; h++ ) {
+ rc = fread( buff, (int)scanWidth, 1, bmpF );
+ dumpBytes( buff, scanWidth, outF );
+ }
+ break;
+ case 4:
+ buff = (char*)malloc(1024);
+ fseek( bmpF, colormapOff, 0 );
+ memset( buff, 0, 1024 );
+ rc = fread( buff, 3*16, 1, bmpF );
+ for (h=15; h>=0; h--) {
+ for (i=3; i>=0; i--)
+ buff[h*4+i] = buff[h*3+i];
+ buff[h*4+3] = 0;
+ }
+ dumpBytes( buff, 1024, outF );
+ rc = fseek( bmpF, bmfhOff, 0 );
+ buff = (char*)realloc( buff, (int)scanWidth*2+10 );
+ width8 = (bmih.width+3)/4*4;
+ for ( h=0; h<bmih.height; h++ ) {
+ rc = fread( buff, (int)scanWidth, 1, bmpF );
+ for (i=scanWidth-1; i>=0; i--) {
+ buff[i*2+1] = buff[i]&0xF;
+ buff[i*2] = (buff[i]>>4)&0xF;
+ }
+ dumpBytes( buff, width8, outF );
+ }
+ break;
+ case 1:
+ buff = (char*)malloc(1024);
+ fseek( bmpF, colormapOff, 0 );
+ memset( buff, 0, 1024 );
+ rc = fread( buff, 3*2, 1, bmpF );
+ for (h=1; h>=0; h--) {
+ for (i=3; i>=0; i--)
+ buff[h*4+i] = buff[h*3+i];
+ buff[h*4+3] = 0;
+ }
+ dumpBytes( buff, 1024, outF );
+ rc = fseek( bmpF, bmfhOff, 0 );
+ buff = (char*)realloc( buff, (int)scanWidth*8+10 );
+ width8 = (bmih.width+3)/4*4;
+ for ( h=0; h<bmih.height; h++ ) {
+ rc = fread( buff, (int)scanWidth, 1, bmpF );
+ for (i=scanWidth-1; i>=0; i--) {
+ for (j=7; j>=0; j--) {
+ buff[i*8+j] = (buff[i]&(128>>j))?1:0;
+ }
+ }
+ dumpBytes( buff, width8, outF );
+ }
+ break;
+ case 24:
+ buff = (char*)malloc( (int)(fullSize) );
+ rc = fread( buff, (int)(fullSize), 1, bmpF );
+ colorTab = (long*)malloc( 1024 );
+ width8 = ((bmih.width+3)/4)*4;
+ conv24to8( colorTab, buff, (int)scanWidth, 3, (int)width8, (int)bmih.height );
+ dumpBytes( (char*)colorTab, 1024, outF );
+ for ( h=0; h<bmih.height; h++ ) {
+ dumpBytes( buff, (int)width8, outF );
+ buff += (int)width8;
+ }
+ break;
+ default:
+ fprintf( stderr, "%s: colors(%d) != 24|8|4|1\n", bmpName, bmih.colors );
+ return;
+ }
+ fprintf( outF, "030000000000\n" );
+ fprintf( outF, "}\n" );
+ }
+ fclose( bmpF );
+}
+
+
+void dumpPng(
+ char * fileName,
+ FILE * outF )
+{
+ FILE * pngF;
+ int rc;
+ unsigned long image_rowbytes, width8, h;
+ long image_width, image_height;
+ int image_channels;
+ unsigned char * image_data;
+ double display_exponent = 1.0;
+
+ int bmih_colors = 24;
+ int bmih_planes = 1;
+
+ long size, fileSize, maxRecSize;
+ long colorTab[1024];
+ char pathName[1024];
+ char ** dir;
+
+ for ( dir=dirs; *dir; dir++ ) {
+ sprintf( pathName, "%s/%s", *dir, fileName );
+ pngF = fopen( pathName, "r" );
+ if ( pngF != NULL )
+ break;
+ }
+
+ if ( pngF == NULL ) {
+ perror( fileName );
+ return;
+ }
+ if ((rc = readpng_init(pngF, (long *) &image_width, (long *) &image_height)) != 0) {
+ switch (rc) {
+ case 1:
+ fprintf(stderr, PROGNAME
+ ": [%s] is not a PNG file: incorrect signature\n",
+ pathName);
+ break;
+ case 2:
+ fprintf(stderr, PROGNAME
+ ": [%s] has bad IHDR (libpng longjmp)\n",
+ pathName);
+ break;
+ case 4:
+ fprintf(stderr, PROGNAME ": insufficient memory\n");
+ break;
+ default:
+ fprintf(stderr, PROGNAME
+ ": unknown readpng_init() error\n");
+ break;
+ }
+ return;
+ }
+
+ image_data = readpng_get_image(display_exponent, &image_channels, &image_rowbytes);
+ width8 = ((image_width+3)/4)*4;
+ size = width8*image_height;
+ fileSize = (size+1024)/2 + 70;
+ maxRecSize = (size+1024)/2 + 34;
+
+ fprintf( outF, "{\\pict\\wmetafile8\\picw%ld\\pich%ld\\picwgoal%ld\\pichgoal%ld\\picbmp\\picbpp%d\n",
+ image_width*26L, image_height*26L, image_width*15L, image_height*15L, 8/*bmih_colors*/ );
+ fprintf( outF, "010009000003%0.8lx0000%0.8lx0000\n",
+ L(fileSize), L(maxRecSize) );
+ fprintf( outF, "050000000b0200000000\n" ); /* SetWindowOrg(0,0) */
+ fprintf( outF, "050000000c02%0.4x%0.4x\n", S((short)image_height), S((short)image_width) );
+ fprintf( outF, "05000000090200000000\n" ); /* SetTextColor( 0 ) */
+ fprintf( outF, "050000000102d8d0c800\n" ); /* SetBkColor( 0 ) */
+ fprintf( outF, "0400000007010300\n" ); /* SetStretchBltMode(0300) */
+ fprintf( outF, "%0.8lx430f\n", L(maxRecSize) );
+ fprintf( outF, "2000cc000000%0.4x%0.4x00000000%0.4x%0.4x00000000\n",
+ S((short)image_height), S((short)image_width), S((short)image_height), S((short)image_width) );
+ fprintf( outF, "28000000%0.8lx%0.8lx%0.4x%0.4x000000000000000000000000000000000000000000000000\n",
+ L(image_width), L(image_height), S(bmih_planes), S(8/*bmih.colors*/) );
+ width8 = ((image_width+3)/4)*4;
+ conv24to8( colorTab, (char *) image_data, image_channels, image_width*image_channels, width8, image_height );
+ dumpBytes( (char *)colorTab, 1024, outF );
+ for ( h=0; h<image_height; h++ ) {
+ dumpBytes( (char *) image_data+(h)*width8, (int)width8, outF );
+ }
+ fprintf( outF, "030000000000\n" );
+ fprintf( outF, "}\n" );
+
+ readpng_cleanup(0);
+ fclose( pngF );
+ free( image_data );
+
+}
+
+void mswwordXref( char * name, char * ref1, char * ref2 )
+{
+ rtfBold( name );
+}
+void mswwordPicture( char * name, int inLine )
+{
+ char tmp[80];
+ if (!inLine) {
+ rtfFlushParagraph();
+ fprintf( ofile, "{\\qc\\sb%d", rtfNeedGap?rtfBigGap:0 );
+ }
+ if ( USE_BMP ) {
+ sprintf( tmp, "%s.bmp", name );
+ dumpBmp( tmp, ofile );
+ } else {
+ sprintf( tmp, "%s.png", name );
+ dumpPng( tmp, ofile );
+ }
+ if (inLine) {
+ /*fprintf( ofile, "\\tab " );*/
+ rtfNeedPar = TRUE;
+ } else {
+ fprintf( ofile, "\\par\\pard}\n" );
+ rtfNeedPar = FALSE;
+ rtfNeedGap = FALSE;
+ rtfGapHeight = -1;
+ }
+}
+int sectionNum[3] = { 0, 0, 0 };
+void mswwordSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ char tmp[1024];
+ char sectionNumS[20];
+ rtfFlushParagraph();
+ if (pageCnt != 0 && newpage) {
+ fprintf( ofile, "\\page\n" );
+ }
+ pageCnt++;
+ if (toc) {
+ fprintf( ofile, "{\\*\\bkmkstart _Toc%ld}\n", tocNum );
+ }
+ fprintf( ofile,"\
+{\\pntext\\pard\\plain\\b\\f5\\fs28\\kerning28 \
+" );
+ switch ( section ) {
+ case 'A':
+ sprintf( sectionNumS, "%d. ", ++sectionNum[0] );
+ sectionNum[1] = sectionNum[2] = 0;
+ break;
+ case 'B':
+ sprintf( sectionNumS, "%d.%d ", sectionNum[0], ++sectionNum[1] );
+ sectionNum[2] = 0;
+ break;
+ case 'C':
+#ifdef LATER
+ sprintf( sectionNumS, "%d.%d.%d ", sectionNum[0], sectionNum[1], ++sectionNum[2] );
+#else
+ sprintf( sectionNumS, "" );
+#endif
+ break;
+ default:
+ sprintf( sectionNumS, "bad section (%c) ", section );
+ }
+ fprintf( ofile, "\
+%s\\tab}\
+\\pard\\plain \\s%d\\sb240\\sa60\\keepn\\widctlpar\
+{\\*\\pn \\pnlvl%d\\pndec\\pnprev1\\pnstart1\\pnindent720\\pnhang\
+{\\pntxta .}\
+}\
+\\b\\f5\\fs28\\kerning28 %s\
+", sectionNumS, section-'A'+1, section-'A'+1, title );
+ if (picture && picture[0] != '\0') {
+ fprintf( ofile, " " );
+ mswwordPicture( picture, 1 );
+ }
+ if (toc) {
+ fprintf( ofile, "{\\*\\bkmkend _Toc%ld}\n", tocNum );
+ }
+ fprintf( ofile, "\
+\\par \
+\\pard\\plain \\widctlpar \\f4\\fs%d \
+\n", FontSize );
+ if (toc) {
+ tocList_p tl;
+ tl = (tocList_p)malloc( sizeof *tl );
+ tl->section = section;
+ tl->title = (char*)malloc( strlen(sectionNumS) + strlen(title) + 1 );
+ sprintf( tl->title, "%s%s", sectionNumS, title );
+ tl->num = tocNum++;
+ tl->next = NULL;
+ if (tocHead == NULL)
+ tocHead = tl;
+ else
+ tocTail->next = tl;
+ tocTail = tl;
+ }
+ rtfNeedPar = FALSE;
+ rtfNeedGap = TRUE;
+ rtfGapHeight = -1;
+}
+
+void mswwordStart( char * inName, char * outName )
+{
+ normalStart( inName, outName );
+ if ( MarginGutter >= 0.0 )
+ fprintf( ofile, "\\margmirror\\gutter%d\n", (int)(MarginGutter*1440.0) );
+ if (MarginTop >= 0.0)
+ fprintf( ofile, "\\margt%d\n", (int)(MarginTop*1440.0) );
+ if (MarginBottom >= 0.0)
+ fprintf( ofile, "\\margb%d\n", (int)(MarginBottom*1440.0) );
+ if (MarginRight >= 0.0)
+ fprintf( ofile, "\\margr%d\n", (int)(MarginRight*1440.0) );
+ if (MarginLeft >= 0.0)
+ fprintf( ofile, "\\margl%d\n", (int)(MarginLeft*1440.0) );
+}
+
+void mswwordFinish( void )
+{
+ char lastSection = 'A';
+ tocList_p tl;
+ rtfFlushParagraph();
+ if (toc) {
+ fprintf( ofile, "\
+\\sect \\sectd \\pgnrestart\\pgnlcrm\\linex0\\endnhere\
+\\pard\\plain \\qc\\widctlpar \\f4\\fs22 \
+{\\b\\fs36\\lang1024\\kerning28 Contents \\par \\par }\
+\\pard\\plain \\s17\\widctlpar\\tqr\\tldot\\tx8640 \\f4\\fs%d\n", FontSize );
+ for ( tl=tocHead; tl; tl=tl->next ) {
+ if ( tl->section != lastSection ) {
+ fprintf( ofile, "\
+\\pard\\plain \\s%d\\li%d\\widctlpar\\tqr\\tldot\\tx8640 \\f4\\fs%d\n",
+ tl->section-'A'+17,
+ (tl->section-'A')*200, FontSize );
+ lastSection = tl->section;
+ }
+ fprintf( ofile, "\
+{\\lang1024\\kerning28 %s}{\\lang1024 \\tab }\
+{\\field{\\*\\fldinst {\\lang1024 GOTOBUTTON _Toc%ld }\n\
+{\\field{\\*\\fldinst {\\lang1024 PAGEREF _Toc%ld }}\
+{\\fldrslt {\\lang1024 3}}}}}{\\lang1024 \\par }\n",
+ tl->title, tl->num, tl->num);
+ }
+ fprintf( ofile,
+"\\pard\\plain \\widctlpar \\f4\\fs%d\n}\n}\n"
+/*\\pard\\plain \*/
+"\\widctlpar \\f4\\fs%d\n" , FontSize, FontSize);
+ }
+ normalFinish();
+}
+
+
+dispatchTable mswwordTable = {
+ mswwordStart,
+ mswwordFinish,
+ rtfNewParagraph,
+ rtfStartLine,
+ rtfBold,
+ rtfItalic,
+ mswwordXref,
+ mswwordPicture,
+ rtfEndLine,
+ rtfPutChar,
+ mswwordSection,
+ (void*)no_op,
+ rtfStartDisplay,
+ (void*)no_op,
+ (void*)no_op,
+ rtfListStart,
+ rtfListItem,
+ rtfListEnd,
+ rtfPage
+ };
+
+/******************************************************************************
+ *
+ * TEXT
+ *
+ *****************************************************************************/
+
+char textBuff[1024];
+char *textBuffP = textBuff;
+int textNewLine = 1;
+int textIndent = 0;
+int textAllowLeadingBlanks = 0;
+int textNoIndent = 0;
+int textLineLength;
+
+void textPutChar( char ch )
+{
+ char *cp, *cq;
+ int indent;
+ int width;
+
+ if (textNewLine) {
+ textLineLength = 0;
+ if (ch == ' ' && !textAllowLeadingBlanks) {
+ return;
+ }
+ if (!textNoIndent) {
+ for (indent=0; indent<textIndent; indent++) {
+ memmove( textBuffP, " ", 4 );
+ textBuffP += 4;
+ textLineLength += 4;
+ }
+ }
+ }
+ textNewLine = 0;
+ *textBuffP++ = ch;
+ if (ch == '\010')
+ textLineLength--;
+ else
+ textLineLength++;
+ width = (textIndent>0?listWidth:lineWidth);
+ if ( wordwrap && width > 0 && textLineLength > width ) {
+ for (cp = textBuffP-1; *cp != ' ' && cp>textBuff+lineWidth/2; cp-- );
+ while ( *cp == ' ' && cp>textBuff+lineWidth/2 ) cp--;
+ cp++;
+ fwrite( textBuff, cp-textBuff, 1, ofile );
+ fwrite( "\n", 1, 1, ofile );
+ textNewLine = 1;
+ while (*cp == ' ' && cp<textBuffP) cp++;
+ if (textBuffP!=cp) {
+ cq = textBuff+textIndent*4;
+ memmove( cq, cp, textBuffP-cp );
+ cq = textBuff;
+ for (indent=0; indent<textIndent; indent++) {
+ memmove( cq, " ", 4 );
+ cq += 4;
+ }
+ textBuffP = cq + (textBuffP-cp);
+ textNewLine = 0;
+ for ( cp=textBuff,textLineLength=0; cp<textBuffP; cp++ ) {
+ if (*cp == '\010')
+ textLineLength--;
+ else
+ textLineLength++;
+ }
+ } else {
+ textBuffP = textBuff;
+ }
+ } else if (textBuffP - textBuff >= sizeof textBuff ) {
+ fwrite( textBuff, textBuffP-textBuff, 1, ofile );
+ textBuffP = textBuff;
+ textLineLength = 0;
+ }
+}
+void textBreakLine( void )
+{
+ if ( !textNewLine ) {
+ fwrite( textBuff, textBuffP-textBuff, 1, ofile );
+ fwrite( "\n", 1, 1, ofile );
+ textNewLine = 1;
+ textBuffP = textBuff;
+ textLineLength = 0;
+ }
+}
+void textSaveLine( char * tmp )
+{
+ if (!textNewLine) {
+ int len = textBuffP-textBuff;
+ memcpy( tmp, textBuff, len );
+ tmp[len] = '\0';
+ textNewLine = 1;
+ textBuffP = textBuff;
+ textLineLength = 0;
+ } else {
+ tmp[0] = '\0';
+ }
+}
+void textRestoreLine( char * tmp )
+{
+ int len = strlen( tmp );
+ if (len > 0) {
+ memcpy( textBuffP, tmp, len );
+ textBuffP += len;
+ textLineLength += len;
+ textNewLine = 0;
+ }
+}
+void textFinish( void )
+{
+ textBreakLine();
+ normalFinish();
+}
+void textPutString( char * cp )
+{
+ while (*cp)
+ textPutChar( *cp++ );
+}
+void textNewParagraph( void )
+{
+ textBreakLine();
+ if (wordwrap) {
+ fwrite( "\n", 1, 1, ofile );
+ }
+}
+void textStartLine( int lastlineblank )
+{
+}
+void textBold( char * name )
+{
+ char * cp;
+ /*textPutChar( '<' );*/
+ for ( cp = name; *cp; cp++ ) {
+ textPutChar( *cp );
+ if (*cp != ' ') {
+ textPutChar( '\010' );
+ textPutChar( *cp );
+ }
+ }
+ /*textPutString( name );*/
+ /*textPutChar( '>' );*/
+}
+void textItalic( char * name )
+{
+ char * cp;
+ /*textPutChar( '<' );*/
+ for ( cp = name; *cp; cp++ ) {
+ textPutChar( *cp );
+ if (*cp != ' ') {
+ textPutChar( '\010' );
+ textPutChar( *cp );
+ }
+ }
+ /*textPutString( name );*/
+ /*textPutChar( '>' );*/
+}
+void textXref( char * name, char * ref1, char * ref2 )
+{
+ textBold( name );
+ /*textPutChar( '<' );
+ textPutString( name );
+ textPutChar( '>' );*/
+ if (ref2) {
+ textPutString( " (See " );
+ textPutString( ref2 );
+ textPutString( " for Details)" );
+ }
+}
+void textPicture( char * picture, int inLine )
+{
+ textPutString( "<<" );
+ textPutString( picture );
+ textPutString( ">>" );
+ if (inLine) {
+ textPutString( " " );
+ } else {
+ textBreakLine();
+ fwrite( "\n", 1, 1, ofile );
+ }
+}
+void textEndLine( void )
+{
+ if ( !wordwrap )
+ textBreakLine();
+}
+void textSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ int len;
+ textBreakLine();
+ if (pageCnt > 0 && newpage) {
+ fwrite( "\014\n", 1, 2, ofile );
+ }
+ pageCnt++;
+ textBold( title );
+ /*textPutString( title );*/
+ textBreakLine();
+ for ( len = strlen(title); len>0; len-- ) {
+ textBold( "=" );
+ /*fwrite( "=", 1, 1, ofile );*/
+ }
+ textBreakLine();
+ fwrite( "\n", 1, 1, ofile );
+}
+void textHeader( char * line )
+{
+}
+void textStartIndent( void )
+{
+ textBreakLine();
+ textIndent++;
+}
+void textEndIndent( void )
+{
+ textBreakLine();
+ if (textIndent < 0) {
+ fprintf( stderr, "%d: textIndent < 0\n", lineNum );
+ textIndent = 0;
+ } else {
+ textIndent--;
+ }
+}
+void textListItem( void )
+{
+ char num[4];
+ textBreakLine();
+ textIndent--;
+ textAllowLeadingBlanks = 1;
+ switch( listType[listLevel] ) {
+ case LISTNONE:
+ default:
+ textPutString( " " );
+ break;
+ case LISTBULLET:
+ textPutString( " o " );
+ break;
+ case LISTDASH:
+ textPutString( " - " );
+ break;
+ case LISTNUMBER:
+ sprintf( num, "%3.3d", listCount[listLevel] );
+ textPutString( num );
+ textPutChar( ' ' );
+ break;
+ }
+ textAllowLeadingBlanks = 0;
+ textIndent++;
+}
+void textPage( void )
+{
+ fwrite( "\014\n", 1, 2, ofile );
+}
+dispatchTable textTable = {
+ normalStart,
+ textFinish,
+ textNewParagraph,
+ textStartLine,
+ textBold,
+ textItalic,
+ textXref,
+ textPicture,
+ textEndLine,
+ textPutChar,
+ textSection,
+ textHeader,
+ textStartIndent,
+ textEndIndent,
+ (void*)no_op,
+ textStartIndent,
+ textListItem,
+ textEndIndent,
+ textPage
+ };
+
+/******************************************************************************
+ *
+ * XVIEW
+ *
+ *****************************************************************************/
+
+
+void xviewStart( char * inName, char * outName )
+{
+ normalStart( inName, outName );
+ lineWidth = 0;
+}
+
+void xviewBold( char * name )
+{
+ char * cp;
+ textPutChar( '<' );
+ textPutString( name );
+ textPutChar( '>' );
+}
+void xviewItalic( char * name )
+{
+ char * cp;
+ textPutChar( '<' );
+ textPutString( name );
+ textPutChar( '>' );
+}
+void xviewXref( char * name, char * ref1, char * ref2 )
+{
+ xviewBold( name );
+ if (ref2) {
+ textPutString( " (See " );
+ textPutString( ref2 );
+ textPutString( " for Details)" );
+ }
+}
+void xviewSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ int indent;
+ int len;
+
+ static char * stars = "************";
+ indent = line[1]-'A'+1;
+ textBreakLine();
+ if (pageCnt > 0 && newpage) {
+ fwrite( "\n", 1, 1, ofile );
+ }
+ if ( newpage ) {
+ pageCnt++;
+ textNoIndent = 1;
+ textPutChar( ':' );
+ textPutString( stars+strlen(stars)-indent );
+ textPutChar( '-' );
+ textPutString( title );
+ textBreakLine();
+ if (context) {
+ textPutChar( ':' );
+ textPutString( context );
+ textPutChar( ' ' );
+ textBreakLine();
+ }
+ }
+ textNoIndent = 0;
+ xviewBold( title );
+ textBreakLine();
+ for ( len = strlen(title); len>0; len-- )
+ fwrite( "=", 1, 1, ofile );
+ fwrite( "\n\n", 1, 2, ofile );
+}
+void xviewHeader( char * line )
+{
+ char tmp[1024];
+ textSaveLine( tmp );
+ textNoIndent = 1;
+ textPutChar( ':' );
+ textPutString( line );
+ textPutChar( ' ' );
+ textBreakLine();
+ textNoIndent = 0;
+ textRestoreLine( tmp );
+}
+dispatchTable xviewTable = {
+ xviewStart,
+ normalFinish,
+ textNewParagraph,
+ textStartLine,
+ xviewBold,
+ xviewItalic,
+ xviewXref,
+ (void*)no_op, /* picture */
+ textEndLine,
+ textPutChar,
+ xviewSection,
+ xviewHeader,
+ textStartIndent, /* startDisplay */
+ textEndIndent, /* endDisplay */
+ (void*)no_op,
+ textStartIndent, /* listStart */
+ textListItem,
+ textEndIndent, /* listEnd */
+ (void*)no_op
+ };
+
+/******************************************************************************
+ *
+ * HTML
+ *
+ *****************************************************************************/
+
+char * htmlName;
+char htmlFileName[1024];
+
+struct {
+ char * name;
+ int index;
+ int section;
+ } links[500];
+int linkCnt = 0;
+
+void setLink( char * name, int sectionNumber )
+{
+ links[linkCnt].name = strdup( name );
+ links[linkCnt].section = sectionNumber;
+ linkCnt++;
+}
+
+
+void getLinks( int sectionNumber, int * prev, int * next )
+{
+ int cur, inx;
+
+ *prev = -1;
+ *next = -1;
+ for ( cur = 0; cur < linkCnt; cur++ ) {
+ if ( links[cur].section == sectionNumber ) {
+ for (inx = cur-1; inx >= 0; inx-- ) {
+ if ( strcmp( links[cur].name, links[inx].name ) == 0 ) {
+ *prev = links[inx].section;
+ break;
+ }
+ }
+ for (inx = cur+1; inx < linkCnt; inx++ ) {
+ if ( strcmp( links[cur].name, links[inx].name ) == 0 ) {
+ *next = links[inx].section;
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+
+struct {
+ char * name;
+ int sectionNumber;
+ int subSection;
+ } sections[500];
+int sectionCnt = 0;
+int lastSection = 0;
+int curSection = 0;
+int subSection = 0;
+
+
+void defineSection( char * name, int sectionNumber )
+{
+ if (!name) {
+ fprintf( stderr, "%d: NULL context string\n", lineNum );
+ return;
+ }
+ sections[sectionCnt].name = strdup( name );
+ sections[sectionCnt].sectionNumber = sectionNumber;
+ if (lastSection != sectionNumber) {
+ subSection = 0;
+ }
+ sections[sectionCnt].subSection = subSection++;
+ sectionCnt++;
+}
+
+
+int lookupSection( char * name, int *subSection )
+{
+ int inx;
+ if (!name) {
+ return -1;
+ }
+ for (inx=0; inx<sectionCnt; inx++) {
+ if (strcmp( name, sections[inx].name ) == 0) {
+ *subSection = sections[inx].subSection;
+ return sections[inx].sectionNumber;
+ }
+ }
+ fprintf( stderr, "%d: undefined reference to %s\n", lineNum, name );
+ return -1;
+}
+
+
+void genHtmlLinks( int sectionNumber, int begin )
+{
+ int prev, next;
+ int comma = 0;
+
+ if (ofile) {
+ if (sectionNumber != 0) {
+ if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" );
+ fprintf( ofile, "<a href=%s.html><b>Return to Contents</b></a>",
+ htmlName );
+ comma = 1;
+ }
+ getLinks( sectionNumber, &prev, &next );
+ if (prev > 0) {
+ if (comma)
+ fprintf( ofile, ", " );
+ else
+ if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" );
+ fprintf( ofile, "<a href=%s-%d.html><b>Previous Page</b></a>",
+ htmlName, prev );
+ comma = 1;
+ }
+ if (next > 0) {
+ if (comma)
+ fprintf( ofile, ", " );
+ else
+ if (!begin) fprintf( ofile, "\n<p></p><p></p><hr><p>" );
+ fprintf( ofile, "<a href=%s-%d.html><b>Next Page</b></a>",
+ htmlName, next );
+ comma = 1;
+ }
+ if (comma)
+ if (begin)
+ fprintf( ofile, "</p><hr><p></p>\n" );
+ else
+ fprintf( ofile, "</p>\n" );
+ }
+}
+
+int preHtmlSectionNumber = -1;
+void preHtmlSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ if ( !newpage )
+ return;
+ preHtmlSectionNumber++;
+ defineSection( context, preHtmlSectionNumber );
+}
+void preHtmlHeader( char * line )
+{
+ if ( line[0] == '*' )
+ return;
+ defineSection( line, preHtmlSectionNumber );
+}
+void preHtmlThread( char * thread )
+{
+ setLink( thread, preHtmlSectionNumber );
+}
+dispatchTable preHtmlTable = {
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ preHtmlSection,
+ preHtmlHeader,
+ (void*)no_op,
+ (void*)no_op,
+ preHtmlThread,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op
+ };
+
+dispatchTable htmlTable;
+
+void htmlStart( char * inName, char * outName )
+{
+ curMode = &preHtmlTable;
+ ifile = openFile( inName );
+ process( ifile );
+ fclose( ifile );
+ curMode = &htmlTable;
+
+ ifile = openFile( inName );
+ htmlName = outName;
+ sprintf( htmlFileName, "%s.html", htmlName );
+ ofile = fopen( htmlFileName, "w" );
+ if (ofile == NULL) {
+ perror( outName );
+ exit( 1 );
+ }
+}
+void htmlFinish( void )
+{
+ genHtmlLinks( curSection, 0 );
+}
+void htmlNewParagraph( void )
+{
+ if (wordwrap) {
+ if ( listLevel < 0 )
+ fprintf( ofile, "<p>" );
+ else
+ fprintf( ofile, "<br>" );
+ } else {
+ fprintf( ofile, "\n" );
+ }
+}
+void htmlStartLine( int lastBlank )
+{
+ if (wordwrap)
+ fprintf( ofile, "\n" );
+ else
+ fprintf( ofile, "\t" );
+}
+void htmlBold( char * name )
+{
+ fprintf( ofile, "<b>%s</b>", name );
+}
+void htmlItalic( char * name )
+{
+ fprintf( ofile, "<i>%s</i>", name );
+}
+void htmlXref( char * name, char * ref1, char * ref2 )
+{
+ int sectionNumber, subSection;
+ sectionNumber = lookupSection( ref1, &subSection );
+ if (sectionNumber < 0)
+ return;
+ fprintf( ofile, "<a href=%s", htmlName );
+ if (sectionNumber != 0)
+ fprintf( ofile, "-%d", sectionNumber );
+ fprintf( ofile, ".html" );
+ if (subSection != 0)
+ fprintf( ofile, "#%d", subSection );
+ fprintf( ofile, ">%s</a>", name );
+}
+void htmlPicture( char * name, int inLine )
+{
+ fprintf( ofile, "<img src=%s.png>", name );
+ if (inLine)
+ fprintf( ofile, "\t" );
+ else
+ fprintf( ofile, "<p></p>\n" );
+}
+void htmlEndLine( void )
+{
+ if ( !wordwrap )
+ fprintf( ofile, "\n" );
+}
+void htmlPutChar( char ch )
+{
+ if ( ch == '<' )
+ fprintf( ofile, "&lt;" );
+ else if ( ch == '>' )
+ fprintf( ofile, "&gt;" );
+ else
+ fputc( ch, ofile );
+}
+void htmlSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ int sectionNumber, subSection;
+ if ( newpage ) {
+ /*if (line[1] == 'A')*/
+ sectionNumber = curSection;
+ curSection = lookupSection( context, &subSection );
+ if (curSection > 0) {
+ genHtmlLinks( sectionNumber, 0 );
+ if (ofile)
+ fclose( ofile );
+ sprintf( htmlFileName, "%s-%d.html", htmlName, curSection );
+ ofile = fopen( htmlFileName, "w" );
+ if (ofile == NULL) {
+ perror( htmlFileName );
+ exit(1);
+ }
+ }
+ fprintf( ofile, "<title>%s</title>\n", title );
+ genHtmlLinks( curSection, 1 );
+ }
+ if (picture && picture[0] != '\0')
+ fprintf( ofile, "<img src=%s.png> ", picture );
+ fprintf( ofile, "<h%d>%s</h%d>\n",
+ line[1]-'A'+1, title, line[1]-'A'+1 );
+}
+void htmlHeader( char * line )
+{
+ int sectionNumber, subSection;
+ if ( line[0] == '*' )
+ return;
+ sectionNumber = lookupSection( line, &subSection );
+ if (sectionNumber < 0)
+ return;
+ fprintf( ofile, "<A Name=\"%d\">\n", sectionNumber );
+}
+void htmlStartDisplay( void )
+{
+ fprintf( ofile, "<p>\n<pre>" );
+}
+void htmlEndDisplay( void )
+{
+ fprintf( ofile, "</pre>\n" );
+}
+void htmlListStart( void )
+{
+ fprintf( ofile, "<ul>" );
+}
+void htmlListItem( void )
+{
+ fprintf( ofile, "<li>" );
+}
+void htmlListEnd( void )
+{
+ fprintf( ofile, "</ul>\n" );
+}
+dispatchTable htmlTable = {
+ htmlStart,
+ htmlFinish,
+ htmlNewParagraph,
+ htmlStartLine,
+ htmlBold,
+ htmlItalic,
+ htmlXref,
+ htmlPicture,
+ htmlEndLine,
+ htmlPutChar,
+ htmlSection,
+ htmlHeader,
+ htmlStartDisplay,
+ htmlEndDisplay,
+ (void*)no_op,
+ htmlListStart,
+ htmlListItem,
+ htmlListEnd,
+ (void*)no_op
+ };
+
+
+/******************************************************************************
+ *
+ * DEFINES
+ *
+ *****************************************************************************/
+struct {
+ char * name;
+ int refCount;
+ int lineNum;
+ } defs[500];
+int defCnt = 0;
+
+void lookupDef( char * name, int def )
+{
+ int inx;
+ if (!name) {
+ fprintf( stderr, "%d: NULL context string\n", lineNum );
+ return;
+ }
+ for (inx=0;inx<defCnt;inx++) {
+ if (strcmp(defs[inx].name,name)==0) {
+ if (def) {
+ if (defs[inx].lineNum <= 0)
+ defs[inx].lineNum = lineNum;
+ else
+ fprintf( stderr, "%d: %s redefined (previous %d)\n",
+ lineNum, name, defs[inx].lineNum );
+ } else {
+ defs[inx].refCount++;
+ }
+ return;
+ }
+ }
+ if (defCnt >= 499) {
+ if (defCnt == 499) {
+ fprintf( stderr, "%d: too many defines\n", lineNum );
+ defCnt++;
+ }
+ return;
+ } else {
+ defs[defCnt].name = strdup( name );
+ defs[defCnt].lineNum = (def?lineNum:-1);
+ defs[defCnt].refCount = 0;
+ defCnt++;
+ }
+}
+
+void defsFinish( void )
+{
+ int inx;
+ for ( inx=0; inx<defCnt; inx++ )
+ fprintf( ofile, "%5d: %s [%d]\n",
+ defs[inx].lineNum, defs[inx].name, defs[inx].refCount );
+ fclose(ofile);
+}
+void defsSection( char section, char * title, char * context, char * picture, char * keywords, int newpage )
+{
+ lookupDef( context, 1 );
+}
+void defsHeader( char * line )
+{
+ if ( line[0] == '*' )
+ return;
+ lookupDef( line, 1 );
+}
+void defsXref( char * name, char * ref1, char * ref2 )
+{
+ lookupDef( ref1, 0 );
+}
+
+dispatchTable defsTable = {
+ normalStart,
+ defsFinish,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ defsXref,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ defsSection,
+ defsHeader,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op,
+ (void*)no_op
+ };
+
+/******************************************************************************
+ *
+ * PARSE
+ *
+ *****************************************************************************/
+
+char * skipChars( char * cp )
+{
+ for ( ; *cp; cp++ ) {
+ if ( *cp != '$' )
+ continue;
+ if ( cp[1] == '{' )
+ continue;
+ break;
+ }
+ return cp;
+}
+
+static int lastlineblank = 0;
+void putline( char * line )
+{
+ int len;
+ char * cp, * cq;
+ char * name;
+ char * mswhelpref;
+ char * xvref;
+ int sectionNumber;
+ int subSection;
+
+ len = strlen(line);
+ if (len > 0 && line[len-1] == '\n')
+ line[--len] = '\0';
+ if (len > 0 && line[len-1] == '\r')
+ line[--len] = '\0';
+ if (len <= 0) {
+ if (lastlineblank)
+ return;
+ curMode->newParagraph();
+ lastlineblank = 1;
+ return;
+ } else {
+ curMode->startLine( lastlineblank );
+ lastlineblank = 0;
+ }
+
+#ifndef LATER
+ if (wordwrap) {
+ if (line[len-1] != ' ') {
+ line[len++] = ' ';
+ if (line[len-2] == '.')
+ line[len++] = ' ';
+ }
+ line[len] = '\0';
+ }
+#endif
+
+ for ( cp=line; *cp; cp++ ) {
+ if (*cp == '$') {
+ cp++;
+ switch (*cp) {
+ case '?':
+ case '$':
+ curMode->putChar( *cp );
+ break;
+ case '{':
+ curMode->putChar( '$' );
+ curMode->putChar( '{' );
+ break;
+ case 'B':
+ name = ++cp;
+ cp = skipChars( cp );
+ if (*cp=='\0')
+ break;
+ *cp = '\0';
+ curMode->doBold( name );
+ break;
+ case 'I':
+ name = ++cp;
+ cp = skipChars( cp );
+ if (*cp=='\0')
+ break;
+ *cp = '\0';
+ curMode->doItalic( name );
+ break;
+ case 'X':
+ name = ++cp;
+ while (*cp && *cp != '|') cp++;
+ if (*cp=='\0')
+ break;
+ *cp++ = '\0';
+ mswhelpref = cp;
+ while (*cp && *cp != '|' && *cp != '$') cp++;
+ if (*cp=='\0')
+ break;
+ if (*cp == '|') {
+ *cp++ = '\0';
+ xvref = cp;
+ while (*cp && *cp != '$') cp++;
+ if (*cp=='\0')
+ break;
+ for (cq=xvref; cq<cp; cq++)
+ if (*cq==',')
+ *cq = '|';
+ } else
+ xvref = NULL;
+ *cp = '\0';
+ curMode->doXref( name, mswhelpref, xvref );
+ break;
+ case 'G':
+ name = ++cp;
+ while (*cp && *cp != '$') cp++;
+ if (*cp=='\0')
+ break;
+ *cp = '\0';
+ curMode->doPicture( name, 1 );
+ break;
+ default:
+ fprintf( stderr, "%d Invalid $ command - %c\n", lineNum, *cp );
+ break;
+ }
+ } else {
+ if (*cp != '\014')
+ curMode->putChar( *cp );
+ }
+ }
+ curMode->endLine();
+}
+
+
+char * conds[100];
+char **condPtr = conds;
+
+void addCond( char * name )
+{
+ *condPtr++ = name;
+}
+int lookupCond( char * name )
+{
+ char ** p;
+ int ret = 1;
+ if (strlen(name) == 0)
+ return 1;
+ if (*name == '!') {
+ ret = 0;
+ name++;
+ }
+ for (p=conds; p<condPtr; p++) {
+ if (strcmp( *p, name )==0)
+ return ret;
+ }
+ return !ret;
+}
+
+void process( FILE * f )
+{
+ char key;
+ char * title;
+ char * context;
+ char * fileName;
+ char * keywords;
+ char * cp;
+ char tmp[1024];
+ int indent;
+ FILE * newFile;
+ int lineNum0;
+ int threadCnt;
+ int sectionNumber;
+ int subSection;
+ int valid;
+ int sectionNewPage;
+ int noSectionNewPage;
+
+ lineNum0 = lineNum;
+ lineNum = 0;
+ while (fgets( line, sizeof line, f ) != NULL) {
+ lineNum++;
+ line[strlen(line)-1] = '\0';
+ if (line[0] == '?' && line[1] == '?') {
+ cp = line+2;
+ while (isblank(*cp)) cp++;
+ if ( strcmp(cp, "else") == 0 )
+ valid = !valid;
+ else
+ valid = lookupCond( cp );
+ continue;
+ }
+ if (!valid) {
+ continue;
+ }
+ if (line[0] == '\014')
+ continue;
+ if (line[0] != '?') {
+ putline( line );
+ continue;
+ }
+ sectionNewPage = 1;
+ switch (line[1]) {
+ case '#':
+ break;
+ case '+':
+ newFile = openFile( line+2 );
+ process( newFile );
+ fclose( newFile );
+ break;
+ case 'a': case 'b': case 'c':
+ line[1] += 'A'-'a';
+ sectionNewPage = 0;
+ case 'A': case 'B': case 'C':
+ if ( noSectionNewPage ) {
+ sectionNewPage = 0;
+ noSectionNewPage = 0;
+ }
+ context = fileName = keywords = NULL;
+ title = cp = line+2;
+ while (*cp && *cp != '|') cp++;
+ if (*cp) {
+ *cp++ = '\0';
+ if (*cp!='|')
+ context = cp;
+ }
+ while (*cp && *cp != '|') cp++;
+ if (*cp) {
+ *cp++ = '\0';
+ if (*cp!='|')
+ fileName = cp;
+ }
+ while (*cp && *cp != '|') cp++;
+ if (*cp) {
+ *cp++ = '\0';
+ if (*cp!='|')
+ keywords = cp;
+ }
+ curMode->doSection( line[1], title, context, fileName, keywords, sectionNewPage );
+ lastlineblank = 0;
+ break;
+ case 'H':
+ curMode->doHeader( line+2 );
+ break;
+ case 'W':
+ if (line[2] == '+') {
+ curMode->doEndDisplay();
+ wordwrap = 1;
+ } else if (line[2] == '-') {
+ curMode->doStartDisplay();
+ wordwrap = 0;
+ } else {
+ fprintf( stderr, "%d: Bad ?W command\n", lineNum);
+ exit(1);
+ }
+ lastlineblank = 0;
+ break;
+ case 'G':
+ curMode->doPicture( line+2, 0 );
+ lastlineblank = 0;
+ break;
+ case 'T':
+ curMode->doThread( line+2 );
+ break;
+ case 'L':
+ switch (line[2]) {
+ case 'S':
+ listLevel++;
+ listCount[listLevel] = 0;
+ switch (line[3]) {
+ case 'o':
+ listType[listLevel] = LISTBULLET;
+ break;
+ case '-':
+ listType[listLevel] = LISTDASH;
+ break;
+ case '1':
+ listType[listLevel] = LISTNUMBER;
+ break;
+ default:
+ listType[listLevel] = LISTNONE;
+ }
+ curMode->doListStart();
+ break;
+ case 'I':
+ if (listLevel<0) {
+ fprintf( stderr, "%d: ?LI not in list\n", lineNum );
+ break;
+ }
+ listCount[listLevel]++;
+ curMode->doListItem();
+ break;
+ case 'E':
+ listLevel--;
+ curMode->doListEnd();
+ break;
+ }
+ lastlineblank = 0;
+ break;
+ case 'P':
+ curMode->page();
+ lastlineblank = 0;
+ break;
+ case 'Q':
+ noSectionNewPage = 1;
+ break;
+ default:
+ fprintf( stderr, "%d: Invalid ? command: %c\n", lineNum, line[1] );
+ }
+ }
+ lineNum = lineNum0;
+}
+
+
+/******************************************************************************
+ *
+ * MAIN
+ *
+ *****************************************************************************/
+
+int main ( int argc, char * argv[] )
+{
+ int inx;
+
+ curMode = NULL;
+ argv++; argc--;
+ while ( argc > 1 && argv[0][0] == '-' ) {
+ if ( strcmp( argv[0], "-xv" ) == 0 ) {
+ curMode = &xviewTable;
+ addCond( "xv" );
+ } else if ( strcmp( argv[0], "-mswhelp" ) == 0 ) {
+ curMode = &mswhelpTable;
+ addCond( "mswhelp" );
+ } else if ( strcmp( argv[0], "-mswword" ) == 0 ) {
+ curMode = &mswwordTable;
+ addCond( "mswword" );
+ } else if ( strcmp( argv[0], "-html" ) == 0 ) {
+ curMode = &htmlTable;
+ addCond( "html" );
+ } else if ( strcmp( argv[0], "-def" ) == 0 ) {
+ curMode = &defsTable;
+ addCond( "def" );
+ } else if ( strcmp( argv[0], "-text" ) == 0 ) {
+ curMode = &textTable;
+ addCond( "text" );
+ } else if ( strncmp( argv[0], "-C", 2 ) == 0 ) {
+ argv++; argc--;
+ addCond( argv[0] );
+ } else if ( strncmp( argv[0], "-v", 2 ) == 0 ) {
+ verbose = 1;
+ } else if ( strncmp( argv[0], "-d", 2 ) == 0 ) {
+ argv++; argc--;
+ *dirList++ = argv[0];
+ } else if ( strncmp( argv[0], "-width", 2 ) == 0 ) {
+ argv++; argc--;
+ listWidth = lineWidth = atoi(argv[0]);
+ if (lineWidth < 10) {
+ fprintf( stderr, "Invalid linewidth %s\n", argv[0] );
+ exit(1);
+ }
+ } else if ( strncmp( argv[0], "-mt", 3 ) == 0 ) {
+ argv++; argc--;
+ MarginTop = atof( *argv );
+ } else if ( strncmp( argv[0], "-mb", 3 ) == 0 ) {
+ argv++; argc--;
+ MarginBottom = atof( *argv );
+ } else if ( strncmp( argv[0], "-mr", 3 ) == 0 ) {
+ argv++; argc--;
+ MarginRight = atof( *argv );
+ } else if ( strncmp( argv[0], "-ml", 3 ) == 0 ) {
+ argv++; argc--;
+ MarginLeft = atof( *argv );
+ } else if ( strncmp( argv[0], "-mg", 3 ) == 0 ) {
+ argv++; argc--;
+ MarginGutter = atof( *argv );
+ } else if ( strncmp( argv[0], "-toc", 4 ) == 0 ) {
+ toc++;
+ } else {
+ fprintf( stderr, "unrecognized option: %s\n", argv[0] );
+ exit( 1 );
+ }
+ argv++;argc--;
+ }
+
+ if (curMode == NULL) {
+ fprintf( stderr, "Must spec either -mswhelp or -xv\n" );
+ exit(1);
+ }
+ if ( argc != 2 ) {
+ fprintf( stderr, "Usage: prochelp [-mswhelp|-xv] <INF> <OUTF>\n" );
+ exit( 1 );
+ }
+
+ curMode->start( argv[0], argv[1] );
+ process( ifile );
+ fclose( ifile );
+ curMode->finish();
+
+ exit(0);
+}
diff --git a/app/help/readpng.c b/app/help/readpng.c
new file mode 100644
index 0000000..1f1d145
--- /dev/null
+++ b/app/help/readpng.c
@@ -0,0 +1,275 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.c
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-1999 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "png.h" /* libpng header; includes zlib.h */
+#include "readpng.h" /* typedefs, common macros, public prototypes */
+
+
+static png_structp png_ptr = NULL;
+static png_infop info_ptr = NULL;
+
+png_uint_32 width, height;
+int bit_depth, color_type;
+uch *image_data = NULL;
+
+
+void readpng_version_info()
+{
+ fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
+ PNG_LIBPNG_VER_STRING, png_libpng_ver);
+ fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
+ ZLIB_VERSION, zlib_version);
+}
+
+
+/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
+
+int readpng_init(FILE *infile, long *pWidth, long *pHeight)
+{
+ uch sig[8];
+
+
+ /* first do a quick check that the file really is a PNG image; could
+ * have used slightly more general png_sig_cmp() function instead */
+
+ fread(sig, 1, 8, infile);
+ if (!png_check_sig(sig, 8))
+ return 1; /* bad signature */
+
+
+ /* could pass pointers to user-defined error handlers instead of NULLs: */
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ return 4; /* out of memory */
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ return 4; /* out of memory */
+ }
+
+
+ /* we could create a second info struct here (end_info), but it's only
+ * useful if we want to keep pre- and post-IDAT chunk info separated
+ * (mainly for PNG-aware image editors and converters) */
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_ptr->jmpbuf)) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ png_init_io(png_ptr, infile);
+ png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
+
+ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
+
+
+ /* alternatively, could make separate calls to png_get_image_width(),
+ * etc., but want bit_depth and color_type for later [don't care about
+ * compression_type and filter_type => NULLs] */
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ NULL, NULL, NULL);
+ *pWidth = width;
+ *pHeight = height;
+
+
+ /* OK, that's all we need for now; return happy */
+
+ return 0;
+}
+
+
+
+
+/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
+ * scales values to 8-bit if necessary */
+
+int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
+{
+ png_color_16p pBackground;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_ptr->jmpbuf)) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
+ return 1;
+
+ /* it is not obvious from the libpng documentation, but this function
+ * takes a pointer to a pointer, and it always returns valid red, green
+ * and blue values, regardless of color_type: */
+
+ png_get_bKGD(png_ptr, info_ptr, &pBackground);
+
+
+ /* however, it always returns the raw bKGD data, regardless of any
+ * bit-depth transformations, so check depth and adjust if necessary */
+
+ if (bit_depth == 16) {
+ *red = pBackground->red >> 8;
+ *green = pBackground->green >> 8;
+ *blue = pBackground->blue >> 8;
+ } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+ if (bit_depth == 1)
+ *red = *green = *blue = pBackground->gray? 255 : 0;
+ else if (bit_depth == 2)
+ *red = *green = *blue = (255/3) * pBackground->gray;
+ else /* bit_depth == 4 */
+ *red = *green = *blue = (255/15) * pBackground->gray;
+ } else {
+ *red = (uch)pBackground->red;
+ *green = (uch)pBackground->green;
+ *blue = (uch)pBackground->blue;
+ }
+
+ return 0;
+}
+
+
+
+
+/* display_exponent == LUT_exponent * CRT_exponent */
+
+uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
+{
+ double gamma;
+ png_uint_32 i, rowbytes;
+ png_bytepp row_pointers = NULL;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_ptr->jmpbuf)) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+
+
+ /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
+ * transparency chunks to full alpha channel; strip 16-bit-per-sample
+ * images to 8 bits per sample; and convert grayscale to RGB[A] */
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand(png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+
+ /* unlike the example in the libpng documentation, we have *no* idea where
+ * this file may have come from--so if it doesn't have a file gamma, don't
+ * do any correction ("do no harm") */
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, display_exponent, gamma);
+
+
+ /* all transformations have been registered; now update info_ptr data,
+ * get rowbytes and channels, and allocate image memory */
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ *pChannels = (int)png_get_channels(png_ptr, info_ptr);
+
+ if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+ if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ free(image_data);
+ image_data = NULL;
+ return NULL;
+ }
+
+ Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
+
+
+ /* set the individual row_pointers to point at the correct offsets */
+
+ for (i = 0; i < height; ++i)
+ row_pointers[height-1-i] = image_data + i*rowbytes;
+
+
+ /* now we can go ahead and just read the whole image */
+
+ png_read_image(png_ptr, row_pointers);
+
+
+ /* and we're done! (png_read_end() can be omitted if no processing of
+ * post-IDAT text/time/etc. is desired) */
+
+ free(row_pointers);
+ row_pointers = NULL;
+
+ png_read_end(png_ptr, NULL);
+
+ return image_data;
+}
+
+
+void readpng_cleanup(int free_image_data)
+{
+ if (free_image_data && image_data) {
+ free(image_data);
+ image_data = NULL;
+ }
+
+ if (png_ptr && info_ptr) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ png_ptr = NULL;
+ info_ptr = NULL;
+ }
+}
diff --git a/app/help/readpng.h b/app/help/readpng.h
new file mode 100644
index 0000000..31780c5
--- /dev/null
+++ b/app/help/readpng.h
@@ -0,0 +1,64 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.h
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-1999 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#ifndef TRUE
+# define TRUE 1
+# define FALSE 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b)? (a) : (b))
+# define MIN(a,b) ((a) < (b)? (a) : (b))
+#endif
+
+#ifdef DEBUG
+# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
+#else
+# define Trace(x) ;
+#endif
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+
+/* prototypes for public functions in readpng.c */
+
+void readpng_version_info(void);
+
+int readpng_init(FILE *infile, long *pWidth, long *pHeight);
+
+int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
+
+uch *readpng_get_image(double display_exponent, int *pChannels,
+ ulg *pRowbytes);
+
+void readpng_cleanup(int free_image_data);
diff --git a/app/help/xtrkcad.info b/app/help/xtrkcad.info
new file mode 100644
index 0000000..39c343e
--- /dev/null
+++ b/app/help/xtrkcad.info
@@ -0,0 +1,1101 @@
+:Help
+Invokes on-line help for this dialog
+:cancel
+Cancels this command
+:Close
+Closes the dialog
+:cmdAbout
+About box dialog
+:cmdAbove
+Move Selected object to top
+:cmdAddElevations
+Raise or Lower all Selected tracks
+:cmdBelow
+Move Selected object to bottom
+:cmdCarDesc
+Create a new Car/Loco description
+:cmdCarInventory
+Manage your Car and Loco Inventory
+:cmdCircleCenter
+Create track circle from center
+:cmdCircleFixedRadius
+Create fixed radius track circle
+:cmdCircleSetCmd
+Set Circle Track creation mode
+:cmdCircleTangent
+Create track circle from tangent
+:cmdClearElevations
+Removes elevation from Selected tracks
+:cmdCmdopt
+Command Options dialog
+:cmdColor
+Controls colors
+:cmdConnect
+Connect two tracks
+:cmdCopy
+Copy selected objects to clipboard
+:cmdCurveCenter
+Create curved track from center
+:cmdCurveChord
+Create curved track from chord
+:cmdCurveEndPt
+Create curved track from end-point
+:cmdCurveSetCmd
+Set Curve Track creation mode
+:cmdCurveTangent
+Create curved track from tangent
+:cmdCustmgm
+Manipulate Custom designer entries
+:cmdCut
+Moves selected objects to clipboard
+:cmdDelete
+Delete objects
+:cmdDemo
+Playback demos
+:cmdDescribe
+Describe objects
+:cmdDeselectAll
+Deselect all selected objects
+:cmdDisplay
+Change Display parameters
+:cmdDrawBench
+Create benchwork
+:cmdDrawBox
+Create a box
+:cmdDrawCircleSetCmd
+Set Circle drawing command
+:cmdDrawCircle
+Create a circle
+:cmdDrawCircleCenter
+Draw a circle line from center
+:cmdDrawCircleFixedRadius
+Draw a fixed radius circle line
+:cmdDrawCircleTangent
+Draw a circle line from tangent
+:cmdDrawCurveSetCmd
+Set Curve drawing command
+:cmdDrawCurve
+Create a curved line
+:cmdDrawCurveEndPt
+Create a curved line from End
+:cmdDrawCurveCenter
+Create a curved line from center
+:cmdDrawCurveChord
+Create a curved line from chord
+:cmdDrawCurveTangent
+Create a curved line from tangent
+:cmdDrawDimLine
+Create a dimension line
+:cmdDrawFilledBox
+Create a filled box
+:cmdDrawFilledCurve
+Create a filled circle
+:cmdDrawFilledCircleCenter
+Draw a filled circle from center
+:cmdDrawFilledCircleFixedRadius
+Draw a fixed radius filled circle
+:cmdDrawFilledCircleTangent
+Draw a filled circle from tangent
+:cmdDrawPolygon
+Create a filled polygon
+:cmdDrawPolyline
+Create a polyline
+:cmdDrawLine
+Create a straight line
+:cmdDrawLineSetCmd
+Set Line drawing command
+:cmdDrawShapeSetCmd
+Set Shape drawing command
+:cmdDrawTableEdge
+Draw table edge
+:cmdEasement
+Easement menu
+:cmdElevation
+Change Elevations
+:cmdEnumerate
+Generate a Parts List of selected objects
+:cmdExport
+Export a .xti file
+:cmdExportDXF
+Export a DXF file
+:cmdFileNote
+General note about the layout
+:cmdFlip
+Flip selected objects
+:cmdGrid
+Adjust snap grid
+:cmdGridEnable
+Enable snap grid
+:cmdGridShow
+Show snap grid
+:cmdGroup
+Create a structure from a Group of objects
+:cmdHandLaidTurnout
+Create a hand-laid turnout
+:cmdHelix
+Create a track helix
+:cmdImport
+Import a .xti file
+:cmdJoin
+Join two tracks
+:cmdLayer
+Change Layers
+:cmdLayerSet
+Selects the current drawing layer
+:cmdLayout
+Layout parameters
+:cmdModify
+Modify or extend a track
+:cmdMove
+Move selected objects
+:cmdMoveLabel
+Move a label
+:cmdMoveToCurrentLayer
+Move selected objects to current layer
+:cmdNote
+Place a note on the layout
+:cmdOutputbitmap
+Print a BitMap
+:cmdParallel
+Create a parallel track
+:cmdParameter
+Register
+:cmdPaste
+Copy objects from clipboard
+:cmdPref
+Perferences dialog
+:cmdPricelist
+Display prices of turnouts, sectional tracks and structures
+:cmdPrint
+Print the layout
+:cmdPrmfile
+Loads and unloads parameter files
+:cmdProfile
+Elevation Profile Command
+:cmdProfileDraw
+Profile
+:cmdRecord
+Command recorder
+:cmdRedo
+Redo last undo
+:cmdRefreshCompound
+Update selected Turnout and Structure definitions
+:cmdRescale
+Rescale selected objects
+:cmdRotate
+Rotate selected object(s)
+:cmdRuler
+Show a ruler
+:cmdSelect
+Select objects
+:cmdSelectAll
+Selects all objects on the layout
+:cmdSelectCurrentLayer
+Selects all objects in the current Layer
+:cmdSelectInvert
+Invert current selection
+:cmdSplitTrack
+Split a track
+:cmdSelectOrphaned
+Select stranded (unconnected) track pieces
+:cmdSticky
+Choose which commands are sticky
+:cmdStraight
+Create straight track
+:cmdStructure
+Place a structure on the layout
+:cmdText
+Enter text on the layout
+:cmdTextSize
+Controls the size of the entered text
+:cmdTip
+Tip of the Day window
+:cmdTrain
+Run Trains
+:cmdTrainPause
+Pause/Resume Trains
+:cmdTrainNewCar
+Place a car on the layout
+:cmdTrainExit
+Exit Trains
+:cmdTunnel
+Hide/Unhide a track
+:cmdTurnout
+Place a turnout or sectional track
+:cmdTurnoutNew
+Create a new turnout definition
+:cmdTurntable
+Place a turntable
+:cmdUpdatetitle
+Updates old source files with 3 part titles
+:cmdUndo
+Undo last command
+:cmdUngroup
+Ungroup objects
+:cmdWidth0
+Draw tracks with thin lines
+:cmdWidth2
+Draw tracks with medium lines
+:cmdWidth3
+Draw tracks with thick lines
+:cmdZoom
+Change drawing scale
+:cmdZoomIn
+Zoom in
+:cmdZoomOut
+Zoom out
+:menuFile
+File Menu
+:menuFile-save
+Save layout
+:menuFile-saveAs
+Save layout under a new name
+:menuFile-clear
+New layout
+:menuFile-enum
+Generate parts list
+:menuFile-load
+Load a layout
+:menuFile-quit
+Exit the program
+:menuFile-revert
+Revert to last saved state of layout plan
+:editM
+Edit menu
+:menuEdit-redraw
+Redraw layout
+:menuEdit-zoomIn
+Zoom in
+:menuEdit-zoomOut
+Zoom out
+:toolsM
+Tools menu
+:menuView
+View menu
+:menuToolbar
+Toolbar configuration
+:menuTools
+Tools menu
+:menuOption
+Options menu
+:menuMacro
+Playback/Record commands
+:menuWindow
+Window menu
+:menuHelp
+Help menu
+:menuHelpRecentMessages
+Recent error messages and explanations
+:hotBarLeft
+Move Hot Bar left
+:hotBarRight
+Move Hot Bar right
+:infoBarCount
+Total track count
+:infoBarPosX
+X Position of cursor
+:infoBarPosY
+Y Position of cursor
+:infoBarScale
+Drawing scale
+:infoBarStatus
+Message and status line
+:main-draw
+Main layout canvas
+:mainDraw
+Main layout canvas
+:main-canvas
+Main drawing canvas
+:main-commandbar
+Command buttons
+:main-menubar
+Menus
+:main-titlebar
+Tile, Filename and Window Manager buttons
+:main-hotbar
+Turnout and Structure Hot Bar
+:main-layers
+Active layer list and layer buttons
+:map-draw
+Map window
+:map-hilight
+This is the portion of the layout shown in the Main Window canvas
+:addElev-value
+Raise or Lower all Selected Track
+:carpart-ok
+Add or Update car object
+:carpart-manuf
+Manufacturer name
+:carpart-prototype
+Car Prototype
+:carpart-prototype-list
+Car Prototype
+:carpart-isLoco
+Is the Car a Locomotive?
+:carpart-partno-list
+Part Number and Description
+:carpart-partno
+Manufacturer Part Number
+:carpart-import
+Use the Selected figure as the car image
+:carpart-reset
+Use the default figure as the car image
+:carpart-desc
+Optional description of the Car Part
+:carpart-flip
+Flip car image
+:carpart-dispmode
+Display Car Item information or reporting marks and dimensions
+:carpart-road
+Full Roadname
+:carpart-type
+Car Type
+:carpart-protokind-list
+Car Type
+:carpart-repmark
+Reporting Marks (Roadname abbreviation)
+:carpart-number
+Car Number
+:carpart-bodyColor
+Car body Color
+:carpart-carLength
+Length of car body
+:carpart-carWidth
+Width of car body
+:carpart-trkCenter
+Distance between Trucks
+:carpart-cplrMount
+Coupler are mounted on body or truck
+:carpart-cpldLen
+Overall Coupled Length
+:carpart-cplrLen
+Coupler Length from end of car
+:carpart-canvas
+Diagram of Car
+:carpart-index
+Item Index Number
+:carpart-purchPrice
+Original Purchase Price
+:carpart-currPrice
+Current Price
+:carpart-condition
+Condition of car
+:carpart-purchDate
+Original Purchase Date
+:carpart-serviceDate
+Last Service Date
+:carpart-quantity
+Number of identical cars to be entered
+:carpart-multinum
+Do all the cars have the same Number?
+:carpart-notes
+Notes about the car
+:carpart-new
+Create a new car Part or Prototype definitions
+:carpart-new-menu
+Create a new car Part or Prototype definitions
+:carinv-ok
+Finds the selected Car Item on the layout
+:carinv-sort1
+Sort the Item list
+:carinv-sort2
+Sort the Item list
+:carinv-sort3
+Sort the Item list
+:carinv-sort4
+Sort the Item list
+:carinv-edit
+Edit the selected Car Item
+:carinv-add
+Add a new Car Item
+:carinv-delete
+Delete the selected Car Items
+:carinv-import
+Import a Car Item .csv file
+:carinv-export
+Export a Car Item .csv file
+:carinv-savetext
+Create a text list of the Car Items
+:circle-radius
+Specifies the radius of the circle track
+:cmdopt-move-quick
+How to draw track being moved/rotated
+:cmdopt-turntable-angle
+Specifies the minimum angle between tracks connected to a turntable
+:cmdopt-preselect
+Default command is Describe or Select
+:cmdopt-coupling-speed-max
+Trains will crash above this speed
+:cmdopt-rightclickmode
+Action to invoke on Right-Click
+:contents-label
+Contents Label for new Parameter file
+:custmgm-inx
+List of custom designed turnouts and structures
+:custmgm-edit
+Invoke designer editor
+:custmgm-delete
+Remove selected entries
+:custmgm-export
+Copy selected entries to Parameter File
+:custmgm-new
+Create a New part or prototype
+:custmgm-ok
+Update custom file and close
+:demo-step
+Executes the next step of the demo
+:demo-next
+Skip to next demo
+:demo-quit
+Stops the demonstration and returns you to XTrkCad
+:demo-speed
+Select speed of Playback
+:demo-text
+This is where comments about the demo are displayed
+:display-tunnels
+Controls the drawing of hidden tracks
+:display-endpt
+Controls the drawing of End-Points
+:display-labelenable
+Enable labels for Turnouts, Flextrack Lengths and Elevations
+:display-description-fontsize
+Font size for labels on layout
+:display-labelscale
+When to label Turnout, Flextrack Lengths and Elevations
+:display-layoutlabels
+Label elements on layout
+:display-color-layers
+Color tracks or other objects by layer
+:display-tworailscale
+Drawing scale when to draw tracks with 2 rails
+:display-tiedraw
+How to draw track ties
+:display-mingridspacing
+Minimum distance (in pixels) between grid lines/ticks
+:display-balloonhelp
+Enable/Disable balloon popup help windows
+:display-hotbarlabels
+Label elements on the Hot Bar
+:display-mapscale
+Drawing scale of the map window
+:display-livemap
+Whether the main layout is updated while dragging on the Map
+:display-carhotbarlabels
+How to group cars on the Train Hot Bar
+:display-hideTrainsInTunnels
+Don't show trains in tunnels when tunnels are hidden
+:draw-linewidth
+Width of the lines
+:draw-linecolor
+Color of the lines
+:draw-benchlist
+List of types of Lumber
+:draw-benchcolor
+Color of Benchwork
+:draw-benchorient
+Orientation of Benchwork
+:draw-arrowsize
+Size of Dimension Arrows
+:easement-val
+This controls the sharpness of the easement curve
+:easement-r
+Minumum radius
+:easement-x
+Maximum offset
+:easement-l
+Easement length
+:easement-radio
+These radio buttons are a short-cut for Values of 0.0, 0.5, 1.0 and 2.0. None turns Easements off
+:easement-ok
+Complete easement selection
+:elev-mode
+Type of elevation
+:elev-value
+Height of End Point
+:elev-computed
+Compute elevation based on neighbors
+:elev-grade
+Compute grade based on neighbors
+:elev-station
+Specify a name for an End-Point
+:enum-print
+Print parts list
+:enum-printsetup
+Invoke the Print Setup dialog
+:enum-save
+Save parts list to file
+:enum-text
+This is the list of parts for the layout
+:enum-list-prices
+Enable prices on the Parts List
+:grid-horzspacing
+Spacing between major grid lines
+:grid-horzdivision
+Allows the spacing to be subdivided
+:grid-horzenable
+Specifies if positions are snaped in this direction
+:grid-vertspacing
+Spacing between major grid lines
+:grid-vertdivision
+Allows the spacing to be subdivided
+:grid-vertenable
+Specifies if positions are snaped in this direction
+:grid-origx
+Shows the origin and angle of the grid
+:grid-origy
+Shows the origin and angle of the grid
+:grid-origa
+Shows the origin and angle of the grid
+:grid-show
+Specifies if the grid is shown
+:grid-ok
+Completes the grid specification
+:group-manuf
+Manufacturer
+:group-desc
+Description
+:group-partno
+Part Number
+:group-segcnt
+Number of segments in Group
+:group-replace
+Replace the Selected object with the new definition?
+:group-ok
+Creates a new Structure (or Turnout)
+:helix-elev
+Elevation difference of Helix End-Points
+:helix-radius
+Helix Radius
+:helix-turns
+Number of turns in the helix
+:helix-angSep
+Angle betweek helix entrance and exit
+:helix-grade
+Grade in helix
+:helix-vertSep
+Separation between helix layers
+:layer-layer
+Layer list
+:layer-name
+Layer Name
+:layer-color
+Color of layer
+:layer-visible
+Layer is drawn on Main window
+:layer-frozen
+Layer cannot be changed
+:layer-onmap
+Layer is drawn on Map window
+:layer-button-count
+Number of layer buttons to show
+:layer-object-count
+Number of objects in this layer
+:layer-reset
+Load layer configuration from default
+:layer-save
+Save current layer configuration as default
+:layer-clear
+Overwrite layer configuration with system default values
+:layout-roomsizeX
+Specifies the size of the room (in inches or centimeters)
+:layout-roomsizeY
+Specifies the size of the room (in inches or centimeters)
+:layout-title1
+Specifies the Title of the layout. This appears on Gaudy printouts
+:layout-title2
+Specifies the Title of the layout. This appears on Gaudy printouts
+:layout-scale
+Specifies the Modelling Scale
+:layout-gauge
+Specifies the rail gauge, ie. the distance between the rails
+:newcar-road
+Roadname
+:newcar-number
+Car Number
+:note-text
+This is the body of the Note. To change this select Modify from the File Menu
+:outputbitmap-density
+Specifies number of pixels per inch (or centimeter)
+:outputbitmap-toggles
+Specifies whether Layout Titles, Borders or Track Centerlines are printed on the BitMap
+:parallel-separation
+Specifies the separation between parallel tracks
+:parameter-name
+Enter your name as specified in the XTrkCad Registration Notice
+:parameter-key
+Enter the key value as specified in the XTrkCad Registration Notice
+:parameter-ok
+Validates the name and key. Terminates the registration command
+:pref-checkpoint
+Specifies the check point frequency
+:pref-units
+Choose english (inches) or metric (centimeters)
+:pref-dstfmt
+How to display length measurements
+:pref-anglesystem
+0° is up or to the right
+:pref-minlength
+Do not create tracks to be shorter than this value
+:pref-connectdistance
+Maximum distance between connected end points
+:pref-connectangle
+Minimum angle between connected End-Points
+:pref-dragpixels
+How far you can move the mouse before its considered a drag
+:pref-dragtimeout
+How long you can hold a mouse button down before its considered a drag
+:pref-autoPan
+Move the Main canvas if you drag near the edge
+:pref-listlabels
+Label elements for lists
+:pref-mintrackradius
+Tracks with tighter radius than this are Exceptional
+:pref-maxtrackgrade
+Tracks with grades steeper than this are Exceptional
+:pref-trainpause
+Delay (in mS) between updating train movements
+:pricelist-cost
+Updated cost of current selected item
+:pricelist-entry
+Item
+:pricelist-inx
+Selection list for prices
+:pricelist-flexlen
+Price of specified length of flex-track
+:pricelist-flexunit
+Price of specified length of flex-track
+:pricelist-flexcost
+Price of specified length of flex-track
+:print-scale
+Controls the reduction (scale) of the printout
+:print-pagew
+Scaled page width (Scale times physical page width)
+:print-max
+Sets page size to the maximum (based on scale and physical page size)
+:print-pageh
+Scaled page height (Scale times physical page height)
+:print-snapshot
+Sets scale, origin and angle for a one page printout of the layout
+:print-format
+Print page in Portrait or Landscape format
+:print-order
+Order of printing pages
+:print-style
+Print Title, Date, Author and other information at bottom of page?
+:print-physsize
+Ignore unprintable page margins?
+:print-registrationMarks
+Print Registration Marks at 1:1?
+:print-grid
+Print Snap Grid?
+:print-ruler
+Print Rulers on all page edges?
+:print-roadbed
+Print Roadbed Outline?
+:print-roadbedWidth
+Print Roadbed Outline
+:print-origx
+Origin of the print grid. This is useful if you want to reprint a set of pages
+:print-origy
+Origin of the print grid. This is useful if you want to reprint a set of pages
+:print-reset
+Resets the origin and angle to 0
+:print-origa
+Origin of the print grid. This is useful if you want to reprint a set of pages
+:print-clear
+Deselects all pages
+:print-setup
+Invoke the Print Setup dialog
+:print-ok
+Print selected pages and terminates the print command
+:prmfile-inx
+List of loaded and unloaded parameter files
+:prmfile-mode
+Show parameter files by names or descriptions
+:prmfile-action
+Toggle the loaded status of the selected parameter file
+:prmfile-browse
+Find a parameter file for loading
+:prmfile-ok
+Update parameter file list
+:profile-canvas
+Profile of specified path
+:profile-clear
+Clear the profile
+:profile-print
+Print the profile
+:record-stop
+Stop recording
+:record-message
+Insert a message
+:record-end
+End a message
+:record-text
+Message body
+:refreshSpecial-list
+Possible turnouts
+:refreshSpecial-skip
+Skip this turnout
+:rename-manuf
+Manufacturer of Object
+:rename-desc
+Description of Object
+:rename-partno
+Part Nuber of Object
+:rescale-toggle
+Rescale by Scale Conversion or by Ratio
+:rescale-fromS
+Original Scale of the selected objects
+:rescale-fromG
+Original Gauge of the selected obkects
+:rescale-toS
+New Scale of the selected objects
+:rescale-toG
+New Gauge of the selected objects
+:rescale-change-dim
+Change track dimensions to new scale
+:rescale-ratio
+Change size by this amount
+:rgbcolor-snapgrid
+Snap Grid Line and Division
+:rgbcolor-marker
+X and Y position markers
+:rgbcolor-border
+Border rulers, room boundaries and table edges
+:rgbcolor-crossmajor
+Primary Axis of grid rotation
+:rgbcolor-crossminor
+Secondary Axis of grid rotation
+:rgbcolor-normal
+Unselected tracks
+:rgbcolor-selected
+Selected tracks
+:rgbcolor-profile
+Color of tracks on the Profile path
+:rgbcolor-exception
+Color of Exceptional tracks
+:rgbcolor-tie
+Color of track ties
+:rgbcolor-ok
+Updates the colors
+:rotate-rotate
+Angle in degrees
+:rotate-ok
+Rotate object(s) by specified amount
+:sticky-set
+Choose commands to be sticky
+:sticky-ok
+Make the commands sticky
+:structure-list
+List of available structure
+:structure-canvas
+Diagram of the selected structure
+:structure-hide
+Hide Selection window when placing Structure
+:structure-stats
+Drawing scale and size
+:structure-ok
+Complete structure placement
+:structure-pier-inx
+Choose a Pier number
+:text-fontsize
+Controls the size of the entered text
+:tip-text
+Useful information about the program
+:tip-showatstart
+Show Tip of the Day every time the program starts
+:tip-next
+Show the next Tip of the Day
+:tip-prev
+Show the previous Tip of the Day
+:toolbarM
+Controls which Command Buttons are displayed
+:train-newcar-index
+List of Cars
+:train-list
+List of active trains
+:train-speed
+Speed
+:train-distance
+Train odometer
+:train-zeroDistance
+Reset odometer to 0
+:train-goto
+Find train on layout
+:train-follow
+Follow train around layout
+:train-autoreverse
+Flip direction at End Of Track
+:train-direction
+Change direction of train
+:train-stop
+Stop the train
+:turnout-list
+List of available turnouts for the current scale
+:turnout-canvas
+Diagram of the currently selected turnout. Click on a End-Point to select the Active End-Point
+:turnout-new
+A menu list of various type of turnouts and sectional tracks you can define
+:turnout-hide
+Hide Selection window when placing Turnout
+:turnout-activeEndPoint
+The selected Active End-Point
+:turnout-current
+Current selected turnout, (displayed in the diagram window)
+:turnout-endPoint
+One the End-Points that can be selected
+:turnoutNew-angle1
+Angle of the specified track to the center line of the turnout
+:turnoutNew-angle2
+Angle of the specified track to the center line of the turnout
+:turnoutNew-angleMode
+Specifies if angles are entered as Frog Numbers or in degrees
+:turnoutNew-desc1
+Desciption
+:turnoutNew-desc2
+Desciption
+:turnoutNew-label
+Turnout description (Manuf., Size, Part Number, etc)
+:turnoutNew-len0
+Length from the base to the end of the specified track
+:turnoutNew-len1
+Length from the base to the end of the specified track
+:turnoutNew-len2
+Length from the base to the end of the specified track
+:turnoutNew-manuf
+Manufacturer
+:turnoutNew-off1
+Offset of the track End-Point from the center line of the turnout
+:turnoutNew-off2
+Offset of the track End-Point from the center line of the turnout
+:turnoutNew-partno1
+Part Number
+:turnoutNew-partno2
+Part Number
+:turnoutNew-print
+Prints a full size diagram of the turnout for checking
+:turnoutNew-ok
+Prints a full size diagram of the turnout for checking
+:turnoutNew-color
+Color of Roadbed lines
+:turnoutNew-roadbedLineWidth
+Width of Roadbed lines
+:turnoutNew-roadbedWidth
+Width of Roadbed
+:turnoutNew-printsetup
+Invoke the Print Setup dialog
+:turnoutNew-done
+Closes the window and returns to the Turnout Selection window
+:turntable-diameter
+Specifies the diameter of the turntable
+:updatetitle-old
+Old Turnout title
+:updatetitle-sel
+List of available titles
+:updatetitle-ignore
+Leave the Turnouts' title unchanged
+:updatetitle-load
+Invoke the Parameter Files dialog
+:updatetitle-list
+List of available turnouts
+:updatetitle-ok
+Update the Turnouts' title
+:fontSelCancel
+Cancel
+:fontSelList
+List
+:fontSelOk
+Ok
+:fontSelSample
+Sample
+:fontSelSize
+Size
+:fontSelSlant
+Slant
+:fontSelW
+Font selection dialog
+:fontSelWeight
+Weight
+:printAbortW
+Printer Abort Window
+:printFileName
+Print to filename
+:printFontAlias
+Specify Postscript font alias mapping
+:printSetup
+Displays the Print Setup window to change printers, orientation, paper size, etc.
+:printSetupCancel
+Closes this dialog
+:printSetupFormat
+Page orientation
+:printSetupMargin
+Unprintable margins
+:printSetupOk
+Updates and closes this dialog
+:printSetupPaper
+Choose paper size
+:printSetupPrinter
+Choose printer
+:printSetupTest
+Print test page
+:about
+No Help
+:about-about
+No Help
+:cmdDebug
+No Help
+:loosen
+No Help
+:misc-toolbarset
+No Help
+:misc-showlayout
+No Help
+:misc-showdisplay
+No Help
+:misc-showcmdopt
+No Help
+:misc-showeasement
+No Help
+:misc-showfontSel
+No Help
+:misc-showgrid
+No Help
+:misc-showdebug
+No Help
+:misc-sticky
+No Help
+:misc-showpref
+No Help
+:misc-showcolor
+No Help
+:misc-showfileClear
+No Help
+:misc-showparamFile
+No Help
+:misc-showpriceList
+No Help
+:misc-showprint
+No Help
+:misc-showprintSetup
+No Help
+:misc-showprintBitmap
+No Help
+:misc-showpartsList
+No Help
+:misc-shownotes
+No Help
+:misc-showundo
+No Help
+:misc-showredo
+No Help
+:misc-showcut
+No Help
+:misc-showcopy
+No Help
+:misc-showpaste
+No Help
+:misc-showdelete
+No Help
+:misc-showtunnel
+No Help
+:misc-showabove
+No Help
+:misc-showbelow
+No Help
+:misc-showwidth0
+No Help
+:misc-showwidth2
+No Help
+:misc-showwidth3
+No Help
+:misc-showrecompelev
+No Help
+:misc-showcardesc
+No Help
+:misc-showcaradd
+No Help
+:misc-showselectAll
+No Help
+:misc-showimport
+No Help
+:misc-showexport
+No Help
+:misc-showexportDXF
+No Help
+:misc-showloosen
+No Help
+:misc-group-objects
+No Help
+:misc-ungroup-objects
+No Help
+:misc-showcustomMgm
+No Help
+:misc-showlayers
+No Help
+:misc-showmoveToCurrentLayer
+No Help
+:misc-showselectCurrentLayer
+No Help
+:misc-showclearElevations
+No Help
+:misc-showaddElevations
+No Help
+:debug-Track
+No Help
+:debug-EndPt
+No Help
+:debug-ReadTracks
+No Help
+:debug-Curve
+No Help
+:debug-Join
+No Help
+:debug-Turnout
+No Help
+:debug-Structure
+No Help
+:debug-Print
+No Help
+:map-canvas
+No Help
+:cmdLayerShow0
+Layer
+:cmdLayerShow1
+Layer
+:cmdLayerShow2
+Layer
+:cmdLayerShow3
+Layer
+:cmdLayerShow4
+Layer
+:cmdLayerShow5
+Layer
+:cmdLayerShow6
+Layer
+:cmdLayerShow7
+Layer
+:cmdLayerShow8
+Layer
+:cmdLayerShow9
+Layer
+:cmdLayerShow10
+Layer
+:cmdLayerShow11
+Layer
+:cmdLayerShow12
+Layer
+:cmdLayerShow13
+Layer
+:cmdLayerShow14
+Layer
+:cmdLayerShow15
+Layer
+:cmdLayerShow16
+Layer
+:cmdLayerShow17
+Layer
+:cmdLayerShow18
+Layer
+:cmdLayerShow19
+Layer
+:
diff --git a/app/help/xtrkcad.tip b/app/help/xtrkcad.tip
new file mode 100644
index 0000000..5887dba
--- /dev/null
+++ b/app/help/xtrkcad.tip
@@ -0,0 +1,235 @@
+XTrackCAD provides demonstrations on most of the program's features. The demos can be run by clicking on the Help menu on the Main window and then selecting Demos.
+
+The notation "Menu|Item" is used in the documentation (and the on-line demos and tips) to indicate the selection of a menu item.\
+For example File|Open means to open the menu by clicking on File on the menu bar of the Main window and then selecting the Open item from that menu.
+
+A number of example layouts are provided. These files are located in the 'examples' directory where you installed XTrackCAD. The "File|Open" command will open that directory when first used.
+
+When installed, the program measures all units in inches. You can change this on the "Options|Preferences" dialog by changing the Units item to Metric instead of English.
+
+You can change the overall size of your layout on the "Options|Layout" dialog.
+
+When installed, the default command is the Describe command. More experienced users will probably want to change this to the Select command. You can do this on the "Options|Command Options" dialog.
+
+Set your modeling scale on the "Options|Layout" dialog. This controls the Turnouts and Structures that are available, Easement values and track gauge.
+
+When Selecting tracks, the connection between Selected and Unselected tracks is marked by a Red X. This indicates points where the connection between tracks will be broken if you Move or Rotate the Selected tracks.
+
+You can change orientation of the pages on the Print command by moving or rotating the Print Grid.\
+Shift-Left-Drag moves the grid and Shift-Right-Drag rotates the grid.
+
+You can add track to any unconnected End-Point with the Modify command.\
+Hold down the Shift key and click on the End-Point and drag away to create a new track segment attached to the End-Point.\
+Repeat with the new End-Point to create flowing tracks.
+
+You can create Curved tracks in four ways by dragging from:\
+ the 1st End-Point in the direction of the curve\
+ Center of the Curve to the 1st End-Point\
+ End-Point to the Center\
+ the 1st to 2nd End-Point\
+Then drag on one of the Red arrows to create the final shape of the curve.\
+\
+You can click on the small button to the left of the Curve command button to change the method.
+
+Track Circles provide a quick way to see what arrangement of tracks will fit in your layout spaces. Create Circles with your typical radius and place them in corners and other locations where your main-line will make changes of direction. This will give you an overall idea of how your layout will look.\
+\
+You can create Circles by:\
+ using a fixed radius\
+ dragging from the Center to edge\
+ dragging from an edge to the Center\
+You can click on the small button to the left of the Circle command button to change the method.
+
+Easements (spiral transition curves) are used when track changes from straight to curved by gradually changing the radius. This improves operation and appearance.\
+Easements are created with Joining or Extending Tracks.\
+The Easement dialog is used to control easements.
+
+"Help|Recent Messages" shows the last error and warning messages that were generated by the program. Also an explanation of each message is displayed.
+
+When creating stall tracks for a turntable, you usually want the the stall tracks to be spaced evenly.\
+The "Turntable Angle" item on "Options|Command Options" dialog can be used specify the minimum angle between stall tracks.
+
+XTrackCAD periodically saves the current layout in a check point file. The 'Check Point' item on the 'Options|Preferences' dialog controls how often the file is saved.\
+You can recover your working file after a system crash by copying the checkpoint file (xtrkcad.ckp in the XTrackCAD Working directory) to file.xtc
+
+The Parallel command is helpful to layout yards and sidings. If the Parallel track abuts with an existing track, it is automatically connected.
+
+You can use Shift-Drag in Select command to move and rotate selected tracks.\
+Shift-Left-Drag moves tracks and Shift-Right-Drag rotates them.\
+Control-Left-Drag can move labels.
+
+You can move and rotate the Snap Grid to align with existing track or benchwork.
+
+Use the Parts List command to measure track length.\
+Select the tracks you want to measure and then click on the Parts List button. The report will list the total of length of the selected flex-track. You will have to add in the length of any Turnouts.
+
+The length of flex-track attached to each Turnout is displayed on layout near the end-points of the Turnouts.\
+Make sure 'Lengths' option of the 'Label Enable' toggle button on the Display dialog is selected.
+
+The Profile command can be used to find the length of a continous section of track.\
+Select the track at the beginning and end of the section. The total length of track will be displayed on the Profile window in the lower right corner.\
+Note: the Profile selects the shortest path between the two selected tracks, which might not be the path you are interested in. In this case, select the first track and then select other tracks along the path.
+
+Layers can be used to contain different groups of tracks or other features. You might use one layer for the main-line, another of staging tracks and another of benchwork.\
+You can give each layer a name (by using the Layer dialog). This name will be displayed as the Balloon Help for the corresponding Layer button, if you have Balloon Help enabled on the Display dialog.
+
+You can remove groups of buttons or the Hot Bar from the Main window to give you more room if you are not using some features. Also, the number of Layer buttons displayed is controlled by the Layers dialog.
+
+The size of the Map window is controlled by the overall size of the room (specified on the Layout dialog) and the Map Scale (on the Display dialog). You can make the Map window larger (or smaller) by decreasing (or increasing) the Map Scale.\
+XTrackCAD will prevent you from making the Map window too small or too large.
+
+You can unload parameter files you are not using by the Parameter Files dialog. This removes unused Turnout and Structure definitions from the Hot Bar and makes the program start faster.
+
+Right-Click on the Main window displays a menu list of commands as an alternative to pressing the buttons on the tool bar or using the menu accelerator keys.
+Holding down the Shift key while you Right-Click will display options for the current command (if any).
+
+Right-Click on the Hot Bar displays a menu of the different groups of objects which you can use to jump to the group you are interested in.\
+Pressing a numeric key (1-9 and 0) moves the Hot Bar to corresponding position (1 is the start, 5 is half way, 0 is the end).
+
+Right-Drag on the Map window sets the origin and scale of the Main window.\
+The Main window will be centered on the spot where you started the Draw and how far you Drag will control how large an area you can see on the Main window.
+
+To refresh the Main window, press Control-L (hold down the 'Ctrl' key and then press the 'l' key).
+
+The File menu contains a list of the last 5 layouts you were working on.
+
+The Print command can optionally print lines representing the roadbed for all tracks. This is useful when printing full size (1:1) for cutting roadbed.
+
+Pressing the 'Esc' key cancels the current command and invokes the default command, (which is either Describe or Select).
+
+When moving or rotating tracks on slow machines or with a large number of tracks, you can improve performance by changing the way tracks are drawn while being moved.\
+Shift-Right click will display a menu containing options to draw tracks normally, as simple lines or just draw end-points.
+
+The colors of different parts of the Main window can be changed with the Colors dialog. In particular, the Snap Grid color can be changed to make it more visible when printed.
+
+By default objects are drawn in their normal colors. Tracks will be drawn in Black. Objects can also be drawn in the color according to their Layer. The color of a Layer is displayed on the corresponding Layer button.\
+The Display dialog 'Color Layers' item has separate toggles for Tracks and non-Tracks.
+
+Each Layer can be drawn or hidden by the 'Visible' toggle on the Layers dialog.
+Short cut Layer buttons can also be displayed on the tool bar for up to the first 20 layers.\
+This buttons allow to Show or Hide the layers.
+
+The name of the Layer is the Balloon Help for the Layer button.
+
+The playback speed of the Demos can be changed by using Speed drop down list on the Demo window.
+
+Many of the commands and dialogs can be invoked by special key combinations called Menu-Accelerators. These are listed on the Menus next to the command name. For example, Control-P will invoke the Print command.
+
+The Connect command is used to join Sectional track pieces that don't quite fit together.\
+This command works by adding small gaps between other tracks to move the selected End-Points closer together.
+
+To copy a group of objects: Select the objects, press Control-C (or select Copy from the Edit menu), press Control-V (or select Paste from the Edit menu).\
+The selected tracks will be copied to the layout and you can Move or Rotate them into position.
+
+In the Rotate (or Select) commands you can press Shift-Right-Click to display the Rotate menu which allows you to rotate the selected objects by a specific angle.
+
+You can use the Move-To-Join option of the Join command (hold down the Shift key) to move a group of Selected tracks to attach with some unselected End-Point.
+
+The Price List dialog (on the File Menu) is used to specify the prices of each type of Turnout, Sectional Track and Structure. Also, the length and price of flex-track pieces can be specified for each scale.\
+This values will be used on the Parts List report to generate total cost of the selected objects.
+
+Areas of water can represented by a Polygon (use the Draw command) of the appropiate color.\
+By using the Modify command, you can move, add or remove corners of the Polygon to fit the shape of the water.\
+You use the Below command to place the Polygon below (or behind) other objects.\
+\
+You can also use a Polygon to represent aisles.
+
+When you create Benchwork you can move it below other objects by Selecting the Benchwork and use the Below command.\
+Also, put Benchwork in a separate Layer so you can hide it if desired.
+
+You can enter Distances and Lengths using any format regardless of the Length Format on the Preferences dialog.
+You can enter Metric values when English is the default Units and vice versa.
+
+When entering Distances and Lengths you can press the '=' key to redisplay the value in the default format.
+You can also press the 's' key to convert a Prototype measurement to a Scale measurement y dividing by the ratio for the current scale.
+The 'p' key will convert a Scale measurement to a Prototype measurement.
+
+You can place cars on the layout using the Train Simulation command to check clearance points, track to track separation and coupling.
+
+Use the MoveTo button on the Custom Management dialog to move your custom Turnout, Structure and Car definitions to a .XTP parameter file.
+
+If you are printing multiple pages on a continuous feed printer (such a Dot Matrix) you can change the Page Order if necessary to print pages out in proper order.
+
+On the Car Item and Car Part dialogs, you can enter custom values for Manufacturer, Part and Road by typing the new value directly into the Drop Down List.
+
+On the Car Item dialog, you can change the Road, Number, Color and other values for a Car. This is useful if you repaint or renumber a car. \
+You can also change the Coupler Mounting and Coupler Length if you change the couplers.
+
+You can Export your Car Inventory to a file in Comma-Separated-Value format which can be read by most spread-sheet programs.
+
+Use the Train Odometer to measure distances along the track.
+
+Holding down the Shift key when clicking the Zoom In or Zoom Out button will zoom to a programmed Drawing Scale. \
+Holding down the Shift and Control keys when clicking a Zoom button will set it's program Zoom to the current Drawing Scale.
+
+You can trim the ends of turnouts by holding down the Shift key when using the Split command.
+
+The Split command can be used to create Block Gaps at end points between two tracks. \
+Either rail or both rails can be gapped, which are drawn as thick lines.
+
+Trains will 'crash' if they hit another car when travelling faster than the 'Max Coupling Speed' (on the Command Options dialog). \
+They will also 'crash' if they hit the end of the track or an open turnout. \
+Crashed trains must be manually moved back onto the track.
+
+You can add new track segments to a turnout definition or create a definition from individual tracks using the Group command.
+
+The center point and radius of Curved and Circle tracks can optionally be drawn. \
+This feature is toggled by using the Move Label command and doing a Shift-Left-Click on the track.
+
+Turnout, Curved and Helix track labels can be individually turned on and off by doing a Shift-Right-Click on the track when using the Move Label command.
+
+You can use the Describe command to change the font size of Text objects.
+
+You can use the Describe command to change the size of Dimension Line labels.
+
+Normally Right-Click displays a popup menu of commands and Shift-Right-Click displays options for the current command. \
+This can reversed by using the Right Click toggle button on the Command Options dialog.
+
+The Align item on the Rotate command options menu will let you Align selected objects with any unselected object. \
+The selected objects are rotated so the first point is parallel to the second point you selected.
+
+Print To Bitmap allows you to print the track center line. \
+This is useful if you later print the bitmap full size as a template when laying track.
+
+You can export the selected tracks to a DXF file which can be read by most CAD programs.
+
+Lengths and distances can be displayed in a variety of units and formats such as 1' 10 3/4", 1ft 10.75in or 22.750. In Metric mode, distances can be displayed as millimeters, centimeters or meters. See the Length Format item on the Preferences dialog.
+
+Tracks that are too steep or curve too tightly are drawn in the Expection color (Purple by default). \
+This helps to identify potential problem areas. \
+The maximum grade and minimum radius are set on the Preferences dialog.
+
+The Flip command produces a mirror-image of the selected tracks. \
+If possible, right-hand turnouts are relabeled as left-hand turnouts (and vice versa).
+
+Then Ungroup command will break turnouts and structures into individual track, line and shape segments. \
+You can modify each segment and add new ones. \
+Then use the Group command to update the definition.
+
+Dimension lines show the distance between two points.
+
+A variety of Benchwork (rectangular, L-girder and T-girder) can be drawn. \
+Use the Below command to move the Benchwork below the track for proper display.
+
+The Turnout Designer dialogs allow you to specify the width of any attached roadbed. \
+As well, the color and thickness of the lines used to represent the roadbed can be specified.
+
+The Color dialog (on the Options menu) is used to change the color of different objects on the display. \
+You can change the color of the Snap Grid and Borders, as well as Normal, Selected and Exception tracks.
+
+#Elevations
+
+#Profile
+
+You can draw tracks with wider lines for rails. \
+Select the tracks and use Medium or Thick Tracks on the Edit menu.
+
+#Custom TO
+
+#Helix
+
+Many objects on the layout have labels: Turnouts/Helix/Curved Titles, Track Lenghts, End-Point Elevations, Track Elevations and Cars. \
+You can turn these labels on or off with the Label Enable toggle buttons on the Display options dialog.
+
+If you hold down the Control key when using the Rotate command, the rotation will be down in increments of 15°.
+
+When using the Rotate command, Shift-Right-Click displays a menu allowing you to rotate by specific amounts or to align the selected objects with another object.
diff --git a/app/help/xvfontsel.hlpsrc b/app/help/xvfontsel.hlpsrc
new file mode 100644
index 0000000..7abab84
--- /dev/null
+++ b/app/help/xvfontsel.hlpsrc
@@ -0,0 +1,25 @@
+The 'Font Select' window lets you choose the font used by your application. The window contains:
+
+?HfontSelList
+A list of available fonts.
+
+?HfontSelWeight
+A Radio button to choose 'Medium' or 'Bold' weight.
+
+?HfontSelSlant
+A Radio button to choose 'Regular' or 'Italic' slant.
+
+?HfontSelOk
+Ok button updates the current font and closes the 'Font Select' window.
+
+?HfontSelCancel
+Cancel button closes the window without updating the current font.
+
+?HfontSelSample
+A canvas which show a sample of the font.
+
+Fonts which do not support the specified weight or slant cannot be selected.
+
+?HfontSelLoading
+Note: loading a font can take a noticeable amount of time, especially if you do not have a FPU.
+
diff --git a/app/help/xvprintsel.hlpsrc b/app/help/xvprintsel.hlpsrc
new file mode 100644
index 0000000..a999c67
--- /dev/null
+++ b/app/help/xvprintsel.hlpsrc
@@ -0,0 +1,73 @@
+The $BPrinter Setup$ dialog allows you configure the application's use of the printer.
+
+The $BPrinter Setup$ window contains:
+
+?LSo
+?HprintSetupPrinter
+?LI
+$BPrinter$ - a list to select a particular printer. The entries on this list are defined by $Bprinter$ lines in the $B~/.xtrkcad/xtrkcad.rc$ file.
+The first entry, 'File', causes printouts to be sent to a file. You will be prompted for a file name when doing a print.
+
+?HprintSetupPaper
+?LI
+$BPaper Size$ - a list of various North American and European paper sizes.
+
+?HprintSetupMargin
+?LI
+$BMargins$ - non-printable margins for particular printers.
+You can adjust these entries or select a printer type from the list.
+To add margins for a new printer, enter the printer's name and then enter the margin for each edge.
+You can use $BPrint Test Page$ to determine the margins for your printer.
+The $BDelete$ button removes a printer from the margin list.
+
+?HprintSetupFormat
+?LI
+$BFormat$ - a Radio button to select either Landscape or Portrait format.
+
+?HFont Alias Map
+?LI
+$BX Font$ and $BPS Font$ - specifies the mapping between the display's X Font and the corresponding PostScript Font.
+You can change the PostScript font for a specifed X Font by typing the new font name in the $BPS Font$ field.
+The $Bfont alias$ map will be printed on the $BPrint Test Page$.
+
+?HprintSetupFontSizeFactor
+?LI
+$BFactor$ - adjusts the scaling between X Font and PostScript Font sizes. Due to differences between the two font systems, text size may be of slightly different between the display and printer. This option allows you to adjust the font size. Normally only a small adjustment is required, (like 0.950).
+
+?HprintSetupOk
+?LI
+$BOk button$ - updates the data and ends the dialog.
+
+?HprintSetupCancel
+?LI
+$BCancel button$ - ends the dialog without update.
+
+?HprintSetupTest
+?LI
+$BPrint Test Page button$ - prints a test page you can use to determine the printer margins.
+?LE
+
+The formats of the $Bprinter$ entries are:
+?W-
+$BWPRINTER.$$Iprinter-num$$B: $$Iprinter-name$$B=$$Icommand$
+?W+
+where:
+?LS-
+?LI
+$Iprinter-num$ is the next value in a sequential list (starting at $B1$, $B0$ is reserved for $BFILE$). $Bprinter.1$ is predefined as $Blp=lpr -P%s$.
+?LI
+$Iprinter-name$ is the name of the printer as it appears in the $BPrinter$ selection list.
+?LI
+$Icommand$ is the command to invoke where $B%s$ will be replaced by the $Iprinter-name$.
+?LE
+
+To add a new $BPrinter$, select the next value for $Iprinter-num$ and add the $Bprinter$ line with the name and print command.
+
+?HprintFontAlias
+Printing generates PostScript data which is sent to the specified printer (or File).
+The names of fonts differs between the X Window System and PostScript and there is no formula to convert them.
+The printing system uses a $Bfont alias$ map to convert from X font names to PostScript font names.
+Font aliases for the common PostScript fonts are predefined but you must supply an alias for unknown fonts.
+The 'Font Alias' window will be shown when ever you are printing an unknown font.
+You will be asked to supply a PostScript font name for a X font.
+You can change the $Bfont alias$ mapping by using the $BX Font$ and $BPS Font$ entries on the $BPrinter Setup$ dialog.