Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * options.c
 * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
 *
 * Description:
 * Read and write the options
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__riscos)
#include "DeskLib:Error.h"
#include "DeskLib:Wimp.h"
#else
#include <stdlib.h>
#if defined(__dos) || defined(N_PLAT_NLM)
extern int getopt(int, char **, const char *);
#else
#include <unistd.h>
#endif /* __dos */
#endif /* __riscos */
#include "antiword.h"

#if defined(__riscos)
#define PARAGRAPH_BREAK         "set paragraph_break=%d"
#define AUTOFILETYPE            "set autofiletype_allowed=%d"
#define USE_OUTLINEFONTS        "set use_outlinefonts=%d"
#define SHOW_IMAGES             "set show_images=%d"
#define HIDE_HIDDEN_TEXT        "set hide_hidden_text=%d"
#define SCALE_FACTOR_START      "set scale_factor_start=%d"
#else
#define LEAFNAME_SIZE           (32+1)
#endif /* __riscos */

/* Current values for options */
static options_type     tOptionsCurr;
#if defined(__riscos)
/* Temporary values for options */
static options_type     tOptionsTemp;
#else
typedef struct papersize_tag {
        char    szName[16];     /* Papersize name */
        USHORT  usWidth;        /* In points */
        USHORT  usHeight;       /* In points */
} papersize_type;

static const papersize_type atPaperSizes[] = {
        {       "10x14",         720,   1008    },
        {       "a3",            842,   1191    },
        {       "a4",            595,    842    },
        {       "a5",            420,    595    },
        {       "b4",            729,   1032    },
        {       "b5",            516,    729    },
        {       "executive",     540,    720    },
        {       "folio",         612,    936    },
        {       "legal",         612,   1008    },
        {       "letter",        612,    792    },
        {       "note",          540,    720    },
        {       "quarto",        610,    780    },
        {       "statement",     396,    612    },
        {       "tabloid",       792,   1224    },
        {       "",                0,      0    },
};
#endif /* __riscos */
/* Default values for options */
static const options_type       tOptionsDefault = {
        DEFAULT_SCREEN_WIDTH,
#if defined(__riscos)
        conversion_draw,
#else
        conversion_text,
#endif /* __riscos */
        TRUE,
        TRUE,
        FALSE,
        encoding_latin_1,
        INT_MAX,
        INT_MAX,
        level_default,
#if defined(__riscos)
        TRUE,
        DEFAULT_SCALE_FACTOR,
#endif /* __riscos */
};


#if !defined(__riscos)
/*
 * bCorrectPapersize - see if the papersize is correct
 *
 * TRUE if the papersize is correct, otherwise FALSE
 */
static BOOL
bCorrectPapersize(const char *szName, conversion_type eConversionType)
{
        const papersize_type    *pPaperSize;

        for (pPaperSize = atPaperSizes;
             pPaperSize->szName[0] != '\0';
             pPaperSize++) {
                if (!STRCEQ(pPaperSize->szName,  szName)) {
                        continue;
                }
                DBG_DEC(pPaperSize->usWidth);
                DBG_DEC(pPaperSize->usHeight);
                tOptionsCurr.eConversionType = eConversionType;
                tOptionsCurr.iPageHeight = (int)pPaperSize->usHeight;
                tOptionsCurr.iPageWidth = (int)pPaperSize->usWidth;
                return TRUE;
        }
        return FALSE;
} /* end of bCorrectPapersize */

/*
 * szCreateSuffix - create a suffix for the file
 *
 * Returns the suffix
 */
static const char *
szCreateSuffix(const char *szLeafname)
{
        const char      *pcDot;

        pcDot = strrchr(szLeafname, '.');
        if (pcDot != NULL && STRCEQ(pcDot, ".txt")) {
                /* There is already a .txt suffix, no need for another one */
                return "";
        }
        return ".txt";
} /* end of szCreateSuffix */

/*
 * eMappingFile2Encoding - convert the mapping file to an encoding
 */
static encoding_type
eMappingFile2Encoding(const char *szLeafname)
{
        char    szMappingFile[LEAFNAME_SIZE+4];

        fail(szLeafname == NULL);

        if (strlen(szLeafname) + 4 >= sizeof(szMappingFile)) {
                DBG_MSG(szLeafname);
                return encoding_latin_1;
        }

        sprintf(szMappingFile, "%s%s", szLeafname, szCreateSuffix(szLeafname));

        DBG_MSG(szMappingFile);

        if (STRCEQ(szMappingFile, MAPPING_FILE_UTF_8)) {
                return encoding_utf_8;
        }
        if (STRCEQ(szMappingFile, MAPPING_FILE_CP852) ||
            STRCEQ(szMappingFile, MAPPING_FILE_CP1250) ||
            STRCEQ(szMappingFile, MAPPING_FILE_8859_2)) {
                return encoding_latin_2;
        }
        if (STRCEQ(szMappingFile, MAPPING_FILE_KOI8_R) ||
            STRCEQ(szMappingFile, MAPPING_FILE_KOI8_U) ||
            STRCEQ(szMappingFile, MAPPING_FILE_CP866) ||
            STRCEQ(szMappingFile, MAPPING_FILE_CP1251) ||
            STRCEQ(szMappingFile, MAPPING_FILE_8859_5)) {
                return encoding_cyrillic;
        }
        return encoding_latin_1;
} /* end of eMappingFile2Encoding */
#endif /* !__riscos */

/*
 * pOpenCharacterMappingFile - open the mapping file
 *
 * Returns the file pointer or NULL
 */
static FILE *
pOpenCharacterMappingFile(const char *szLeafname)
{
#if !defined(__riscos)
        FILE    *pFile;
        const char      *szHome, *szAntiword, *szSuffix;
        size_t  tFilenameLen;
        char    szMappingFile[PATH_MAX+1];
#endif /* !__riscos */

        if (szLeafname == NULL || szLeafname[0] == '\0') {
                return NULL;
        }

        DBG_MSG(szLeafname);

#if defined(__riscos)
        return fopen(szLeafname, "r");
#else
        /* Set the suffix */
        szSuffix = szCreateSuffix(szLeafname);

        /* Set length */
        tFilenameLen = strlen(szLeafname) + strlen(szSuffix);

        /* Try the environment version of the mapping file */
        szAntiword = szGetAntiwordDirectory();
        if (szAntiword != NULL && szAntiword[0] != '\0') {
            if (strlen(szAntiword) + tFilenameLen <
                sizeof(szMappingFile) -
                sizeof(FILE_SEPARATOR)) {
                        sprintf(szMappingFile,
                                "%s" FILE_SEPARATOR "%s%s",
                                szAntiword, szLeafname, szSuffix);
                        DBG_MSG(szMappingFile);
                        pFile = fopen(szMappingFile, "r");
                        if (pFile != NULL) {
                                return pFile;
                        }
                } else {
                        werr(0, "Environment mappingfilename ignored");
                }
        }

        /* Try the local version of the mapping file */
        szHome = szGetHomeDirectory();
        if (strlen(szHome) + tFilenameLen <
            sizeof(szMappingFile) -
            sizeof(ANTIWORD_DIR) -
            2 * sizeof(FILE_SEPARATOR)) {
                sprintf(szMappingFile,
                        "%s" FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR "%s%s",
                        szHome, szLeafname, szSuffix);
                DBG_MSG(szMappingFile);
                pFile = fopen(szMappingFile, "r");
                if (pFile != NULL) {
                        return pFile;
                }
        } else {
                werr(0, "Local mappingfilename too long, ignored");
        }

        /* Try the global version of the mapping file */
        if (tFilenameLen <
            sizeof(szMappingFile) -
            sizeof(GLOBAL_ANTIWORD_DIR) -
            sizeof(FILE_SEPARATOR)) {
                sprintf(szMappingFile,
                        GLOBAL_ANTIWORD_DIR FILE_SEPARATOR "%s%s",
                        szLeafname, szSuffix);
                DBG_MSG(szMappingFile);
                pFile = fopen(szMappingFile, "r");
                if (pFile != NULL) {
                        return pFile;
                }
        } else {
                werr(0, "Global mappingfilename too long, ignored");
        }
        werr(0, "I can't open your mapping file (%s%s)\n"
                "It is not in '%s" FILE_SEPARATOR ANTIWORD_DIR "' nor in '"
                GLOBAL_ANTIWORD_DIR "'.", szLeafname, szSuffix, szHome);
        return NULL;
#endif /* __riscos */
} /* end of pOpenCharacterMappingFile */

/*
 * vCloseCharacterMappingFile - close the mapping file
 */
static void
vCloseCharacterMappingFile(FILE *pFile)
{
        (void)fclose(pFile);
} /* end of pCloseCharacterMappingFile */


/*
 * iReadOptions - read options
 *
 * returns:     -1: error
 *               0: help
 *              >0: index first file argument
 */
int
iReadOptions(int argc, char **argv)
{
#if defined(__riscos)
        FILE    *pFile;
        const char      *szAlphabet;
        int     iAlphabet;
        char    szLine[81];
#else
        extern  char    *optarg;
        extern int      optind;
        char    *pcChar, *szTmp;
        int     iChar;
        char    szLeafname[LEAFNAME_SIZE];
#endif /* __riscos */
        FILE    *pCharacterMappingFile;
        int     iTmp;
        BOOL    bSuccess;

        DBG_MSG("iReadOptions");

/* Defaults */
        tOptionsCurr = tOptionsDefault;

#if defined(__riscos)
/* Choices file */
        pFile = fopen("<AntiWord$ChoicesFile>", "r");
        DBG_MSG_C(pFile == NULL, "Choices file not found");
        DBG_HEX_C(pFile != NULL, pFile);
        if (pFile != NULL) {
                while (fgets(szLine, (int)sizeof(szLine), pFile) != NULL) {
                        DBG_MSG(szLine);
                        if (szLine[0] == '#' ||
                            szLine[0] == '\r' ||
                            szLine[0] == '\n') {
                                continue;
                        }
                        if (sscanf(szLine, PARAGRAPH_BREAK, &iTmp) == 1 &&
                            (iTmp == 0 ||
                            (iTmp >= MIN_SCREEN_WIDTH &&
                             iTmp <= MAX_SCREEN_WIDTH))) {
                                tOptionsCurr.iParagraphBreak = iTmp;
                                DBG_DEC(tOptionsCurr.iParagraphBreak);
                        } else if (sscanf(szLine, AUTOFILETYPE, &iTmp)
                                                                == 1) {
                                tOptionsCurr.bAutofiletypeAllowed =
                                                                iTmp != 0;
                                DBG_DEC(tOptionsCurr.bAutofiletypeAllowed);
                        } else if (sscanf(szLine, USE_OUTLINEFONTS, &iTmp)
                                                                == 1) {
                                tOptionsCurr.eConversionType =
                                        iTmp == 0 ?
                                        conversion_text : conversion_draw;
                                DBG_DEC(tOptionsCurr.eConversionType);
                        } else if (sscanf(szLine, SHOW_IMAGES, &iTmp)
                                                                == 1) {
                                tOptionsCurr.eImageLevel = iTmp != 0 ?
                                        level_default : level_no_images;
                        } else if (sscanf(szLine, HIDE_HIDDEN_TEXT, &iTmp)
                                                                == 1) {
                                tOptionsCurr.bHideHiddenText = iTmp != 0;
                                DBG_DEC(tOptionsCurr.bHideHiddenText);
                        } else if (sscanf(szLine, SCALE_FACTOR_START, &iTmp)
                                                                == 1) {
                                if (iTmp >= MIN_SCALE_FACTOR &&
                                    iTmp <= MAX_SCALE_FACTOR) {
                                        tOptionsCurr.iScaleFactor = iTmp;
                                        DBG_DEC(tOptionsCurr.iScaleFactor);
                                }
                        }
                }
                (void)fclose(pFile);
        }
        iAlphabet = iReadCurrentAlphabetNumber();
        switch (iAlphabet) {
        case 101:       /* ISO-8859-1 aka Latin1 */
                szAlphabet = "<AntiWord$Latin1>";
                break;
        case 112:       /* ISO-8859-15 aka Latin9 */
                szAlphabet = "<AntiWord$Latin9>";
                break;
        default:
                werr(0, "Alphabet '%d' is not supported", iAlphabet);
                return -1;
        }
        pCharacterMappingFile = pOpenCharacterMappingFile(szAlphabet);
        if (pCharacterMappingFile != NULL) {
                bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
                vCloseCharacterMappingFile(pCharacterMappingFile);
        } else {
                bSuccess = FALSE;
        }
        return bSuccess ? 1 : -1;
#else
/* Environment */
        szTmp = getenv("COLUMNS");
        if (szTmp != NULL) {
                DBG_MSG(szTmp);
                iTmp = (int)strtol(szTmp, &pcChar, 10);
                if (*pcChar == '\0') {
                        iTmp -= 4;      /* This is for the edge */
                        if (iTmp < MIN_SCREEN_WIDTH) {
                                iTmp = MIN_SCREEN_WIDTH;
                        } else if (iTmp > MAX_SCREEN_WIDTH) {
                                iTmp = MAX_SCREEN_WIDTH;
                        }
                        tOptionsCurr.iParagraphBreak = iTmp;
                        DBG_DEC(tOptionsCurr.iParagraphBreak);
                }
        }
        strncpy(szLeafname, szGetDefaultMappingFile(), sizeof(szLeafname) - 1);
        szLeafname[sizeof(szLeafname) - 1] = '\0';
/* Command line */
        while ((iChar = getopt(argc, argv, "La:fhi:m:p:rstw:x:")) != -1) {
                switch (iChar) {
                case 'L':
                        tOptionsCurr.bUseLandscape = TRUE;
                        break;
                case 'a':
                        if (!bCorrectPapersize(optarg, conversion_pdf)) {
                                werr(0, "-a without a valid papersize");
                                return -1;
                        }
                        break;
                case 'f':
                        tOptionsCurr.eConversionType = conversion_fmt_text;
                        break;
                case 'h':
                        return 0;
                case 'i':
                        iTmp = (int)strtol(optarg, &pcChar, 10);
                        if (*pcChar != '\0') {
                                break;
                        }
                        switch (iTmp) {
                        case 0:
                                tOptionsCurr.eImageLevel = level_gs_special;
                                break;
                        case 1:
                                tOptionsCurr.eImageLevel = level_no_images;
                                break;
                        case 2:
                                tOptionsCurr.eImageLevel = level_ps_2;
                                break;
                        case 3:
                                tOptionsCurr.eImageLevel = level_ps_3;
                                break;
                        default:
                                tOptionsCurr.eImageLevel = level_default;
                                break;
                        }
                        DBG_DEC(tOptionsCurr.eImageLevel);
                        break;
                case 'm':
                        if (tOptionsCurr.eConversionType == conversion_xml) {
                                werr(0, "XML doesn't need a mapping file");
                                break;
                        }
                        strncpy(szLeafname, optarg, sizeof(szLeafname) - 1);
                        szLeafname[sizeof(szLeafname) - 1] = '\0';
                        DBG_MSG(szLeafname);
                        break;
                case 'p':
                        if (!bCorrectPapersize(optarg, conversion_ps)) {
                                werr(0, "-p without a valid papersize");
                                return -1;
                        }
                        break;
                case 'r':
                        tOptionsCurr.bRemoveRemovedText = FALSE;
                        break;
                case 's':
                        tOptionsCurr.bHideHiddenText = FALSE;
                        break;
                case 't':
                        tOptionsCurr.eConversionType = conversion_text;
                        break;
                case 'w':
                        iTmp = (int)strtol(optarg, &pcChar, 10);
                        if (*pcChar == '\0') {
                                if (iTmp != 0 && iTmp < MIN_SCREEN_WIDTH) {
                                        iTmp = MIN_SCREEN_WIDTH;
                                } else if (iTmp > MAX_SCREEN_WIDTH) {
                                        iTmp = MAX_SCREEN_WIDTH;
                                }
                                tOptionsCurr.iParagraphBreak = iTmp;
                                DBG_DEC(tOptionsCurr.iParagraphBreak);
                        }
                        break;
                case 'x':
                        if (STREQ(optarg, "db")) {
                                tOptionsCurr.iParagraphBreak = 0;
                                tOptionsCurr.eConversionType = conversion_xml;
                                strcpy(szLeafname, MAPPING_FILE_UTF_8);
                        } else {
                                werr(0, "-x %s is not supported", optarg);
                                return -1;
                        }
                        break;
                default:
                        return -1;
                }
        }

        tOptionsCurr.eEncoding = eMappingFile2Encoding(szLeafname);
        DBG_DEC(tOptionsCurr.eEncoding);

        if (tOptionsCurr.eConversionType == conversion_ps &&
            tOptionsCurr.eEncoding == encoding_utf_8) {
                werr(0,
                "The combination PostScript and UTF-8 is not supported");
                return -1;
        }

        if (tOptionsCurr.eConversionType == conversion_pdf &&
            tOptionsCurr.eEncoding == encoding_utf_8) {
                werr(0,
                "The combination PDF and UTF-8 is not supported");
                return -1;
        }

        if (tOptionsCurr.eConversionType == conversion_pdf &&
            tOptionsCurr.eEncoding == encoding_cyrillic) {
                werr(0,
                "The combination PDF and Cyrillic is not supported");
                return -1;
        }

        if (tOptionsCurr.eConversionType == conversion_ps ||
            tOptionsCurr.eConversionType == conversion_pdf) {
                /* PostScript or PDF mode */
                if (tOptionsCurr.bUseLandscape) {
                        /* Swap the page height and width */
                        iTmp = tOptionsCurr.iPageHeight;
                        tOptionsCurr.iPageHeight = tOptionsCurr.iPageWidth;
                        tOptionsCurr.iPageWidth = iTmp;
                }
                /* The paragraph break depends on the width of the paper */
                tOptionsCurr.iParagraphBreak = iMilliPoints2Char(
                        (long)tOptionsCurr.iPageWidth * 1000 -
                        lDrawUnits2MilliPoints(
                                PS_LEFT_MARGIN + PS_RIGHT_MARGIN));
                DBG_DEC(tOptionsCurr.iParagraphBreak);
        }

        pCharacterMappingFile = pOpenCharacterMappingFile(szLeafname);
        if (pCharacterMappingFile != NULL) {
                bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
                vCloseCharacterMappingFile(pCharacterMappingFile);
        } else {
                bSuccess = FALSE;
        }
        return bSuccess ? optind : -1;
#endif /* __riscos */
} /* end of iReadOptions */

/*
 * vGetOptions - get a copy of the current option values
 */
void
vGetOptions(options_type *pOptions)
{
        fail(pOptions == NULL);

        *pOptions = tOptionsCurr;
} /* end of vGetOptions */

#if defined(__riscos)
/*
 * vWriteOptions - write the current options to the Options file
 */
static void
vWriteOptions(void)
{
        FILE    *pFile;
        char    *szOptionsFile;

        TRACE_MSG("vWriteOptions");

        szOptionsFile = getenv("AntiWord$ChoicesSave");
        if (szOptionsFile == NULL) {
                werr(0, "Warning: Name of the Choices file not found");
                return;
        }
        if (!bMakeDirectory(szOptionsFile)) {
                werr(0,
                "Warning: I can't make a directory for the Choices file");
                return;
        }
        pFile = fopen(szOptionsFile, "w");
        if (pFile == NULL) {
                werr(0, "Warning: I can't write the Choices file");
                return;
        }
        (void)fprintf(pFile, PARAGRAPH_BREAK"\n",
                tOptionsCurr.iParagraphBreak);
        (void)fprintf(pFile, AUTOFILETYPE"\n",
                tOptionsCurr.bAutofiletypeAllowed);
        (void)fprintf(pFile, USE_OUTLINEFONTS"\n",
                tOptionsCurr.eConversionType == conversion_text ? 0 : 1);
        (void)fprintf(pFile, SHOW_IMAGES"\n",
                tOptionsCurr.eImageLevel == level_no_images ? 0 : 1);
        (void)fprintf(pFile, HIDE_HIDDEN_TEXT"\n",
                tOptionsCurr.bHideHiddenText);
        (void)fprintf(pFile, SCALE_FACTOR_START"\n",
                tOptionsCurr.iScaleFactor);
        (void)fclose(pFile);
} /* end of vWriteOptions */

/*
 * vChoicesOpenAction - action to be taken when the Choices window opens
 */
void
vChoicesOpenAction(window_handle tWindow)
{
        TRACE_MSG("vChoicesOpenAction");

        tOptionsTemp = tOptionsCurr;
        if (tOptionsTemp.iParagraphBreak == 0) {
                vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, FALSE);
                vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, TRUE);
                vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
                                        DEFAULT_SCREEN_WIDTH);
        } else {
                vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
                vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
                vUpdateWriteableNumber(tWindow,
                        CHOICES_BREAK_WRITEABLE,
                        tOptionsTemp.iParagraphBreak);
        }
        vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
                                        tOptionsTemp.bAutofiletypeAllowed);
        vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
                                        tOptionsTemp.bHideHiddenText);
        if (tOptionsTemp.eConversionType == conversion_draw) {
                vUpdateRadioButton(tWindow,
                        CHOICES_WITH_IMAGES_BUTTON,
                        tOptionsTemp.eImageLevel != level_no_images);
                vUpdateRadioButton(tWindow,
                        CHOICES_NO_IMAGES_BUTTON,
                        tOptionsTemp.eImageLevel == level_no_images);
                vUpdateRadioButton(tWindow,
                        CHOICES_TEXTONLY_BUTTON, FALSE);
        } else {
                vUpdateRadioButton(tWindow,
                        CHOICES_WITH_IMAGES_BUTTON, FALSE);
                vUpdateRadioButton(tWindow,
                        CHOICES_NO_IMAGES_BUTTON, FALSE);
                vUpdateRadioButton(tWindow,
                        CHOICES_TEXTONLY_BUTTON, TRUE);
        }
        vUpdateWriteableNumber(tWindow,
                CHOICES_SCALE_WRITEABLE, tOptionsTemp.iScaleFactor);
        TRACE_MSG("end of vChoicesOpenAction");
} /* end of vChoicesOpenAction */

/*
 * vDefaultButtonAction - action when the default button is clicked
 */
static void
vDefaultButtonAction(window_handle tWindow)
{
        TRACE_MSG("vDefaultButtonAction");

        tOptionsTemp = tOptionsDefault;
        vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
        vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
        vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
                        tOptionsTemp.iParagraphBreak);
        vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
                        tOptionsTemp.bAutofiletypeAllowed);
        vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
                        tOptionsTemp.bHideHiddenText);
        vUpdateRadioButton(tWindow, CHOICES_WITH_IMAGES_BUTTON,
                        tOptionsTemp.eConversionType == conversion_draw &&
                        tOptionsTemp.eImageLevel != level_no_images);
        vUpdateRadioButton(tWindow, CHOICES_NO_IMAGES_BUTTON,
                        tOptionsTemp.eConversionType == conversion_draw &&
                        tOptionsTemp.eImageLevel == level_no_images);
        vUpdateRadioButton(tWindow, CHOICES_TEXTONLY_BUTTON,
                        tOptionsTemp.eConversionType == conversion_text);
        vUpdateWriteableNumber(tWindow, CHOICES_SCALE_WRITEABLE,
                        tOptionsTemp.iScaleFactor);
} /* end of vDefaultButtonAction */

/*
 * vApplyButtonAction - action to be taken when the OK button is clicked
 */
static void
vApplyButtonAction(void)
{
        TRACE_MSG("vApplyButtonAction");

        tOptionsCurr = tOptionsTemp;
} /* end of vApplyButtonAction */

/*
 * vSaveButtonAction - action to be taken when the save button is clicked
 */
static void
vSaveButtonAction(void)
{
        TRACE_MSG("vSaveButtonAction");

        vApplyButtonAction();
        vWriteOptions();
} /* end of vSaveButtonAction */

/*
 * vSetParagraphBreak - set the paragraph break to the given number
 */
static void
vSetParagraphBreak(window_handle tWindow, int iNumber)
{
        tOptionsTemp.iParagraphBreak = iNumber;
        if (tOptionsTemp.iParagraphBreak == 0) {
                return;
        }
        vUpdateWriteableNumber(tWindow,
                        CHOICES_BREAK_WRITEABLE,
                        tOptionsTemp.iParagraphBreak);
} /* end of vSetParagraphBreak */

/*
 * vChangeParagraphBreak - change the paragraph break with the given number
 */
static void
vChangeParagraphBreak(window_handle tWindow, int iNumber)
{
        int     iTmp;

        iTmp = tOptionsTemp.iParagraphBreak + iNumber;
        if (iTmp < MIN_SCREEN_WIDTH || iTmp > MAX_SCREEN_WIDTH) {
                /* Ignore */
                return;
        }
        tOptionsTemp.iParagraphBreak = iTmp;
        vUpdateWriteableNumber(tWindow,
                        CHOICES_BREAK_WRITEABLE,
                        tOptionsTemp.iParagraphBreak);
} /* end of vChangeParagraphBreak */

/*
 * vChangeAutofiletype - invert the permission to autofiletype
 */
static void
vChangeAutofiletype(window_handle tWindow)
{
        tOptionsTemp.bAutofiletypeAllowed =
                                !tOptionsTemp.bAutofiletypeAllowed;
        vUpdateRadioButton(tWindow,
                        CHOICES_AUTOFILETYPE_BUTTON,
                        tOptionsTemp.bAutofiletypeAllowed);
} /* end of vChangeAutofiletype */

/*
 * vChangeHiddenText - invert the hide/show hidden text
 */
static void
vChangeHiddenText(window_handle tWindow)
{
        tOptionsTemp.bHideHiddenText = !tOptionsTemp.bHideHiddenText;
        vUpdateRadioButton(tWindow,
                        CHOICES_HIDDEN_TEXT_BUTTON,
                        tOptionsTemp.bHideHiddenText);
} /* end of vChangeHiddenText */

/*
 * vUseFontsImages - use outline fonts, show images
 */
static void
vUseFontsImages(BOOL bUseOutlineFonts, BOOL bShowImages)
{
        tOptionsTemp.eConversionType =
                bUseOutlineFonts ? conversion_draw : conversion_text;
        tOptionsTemp.eImageLevel =
                bUseOutlineFonts && bShowImages ?
                level_default : level_no_images;
} /* end of vUseFontsImages */

/*
 * vSetScaleFactor - set the scale factor to the given number
 */
static void
vSetScaleFactor(window_handle tWindow, int iNumber)
{
        tOptionsTemp.iScaleFactor = iNumber;
        vUpdateWriteableNumber(tWindow,
                        CHOICES_SCALE_WRITEABLE,
                        tOptionsTemp.iScaleFactor);
} /* end of vSetScaleFactor */

/*
 * vChangeScaleFactor - change the scale factor with the given number
 */
static void
vChangeScaleFactor(window_handle tWindow, int iNumber)
{
        int     iTmp;

        iTmp = tOptionsTemp.iScaleFactor + iNumber;
        if (iTmp < MIN_SCALE_FACTOR || iTmp > MAX_SCALE_FACTOR) {
                /* Ignore */
                return;
        }
        tOptionsTemp.iScaleFactor = iTmp;
        vUpdateWriteableNumber(tWindow,
                        CHOICES_SCALE_WRITEABLE,
                        tOptionsTemp.iScaleFactor);
} /* end of vChangeScaleFactor */

/*
 * bChoicesMouseClick - handle a mouse click in the Choices window
 */
BOOL
bChoicesMouseClick(event_pollblock *pEvent, void *pvReference)
{
        icon_handle     tAction;
        mouse_block     *pMouse;
        BOOL            bCloseWindow;

        TRACE_MSG("bChoicesMouseClick");

        fail(pEvent == NULL);
        fail(pEvent->type != event_CLICK);

        pMouse = &pEvent->data.mouse;
        if (!pMouse->button.data.select && !pMouse->button.data.adjust) {
                /* Not handled here */
                DBG_HEX(pMouse->button.value);
                return FALSE;
        }

        /* Which action should be taken */
        tAction = pMouse->icon;
        if (pMouse->button.data.adjust) {
                /* The adjust button reverses the direction */
                switch (pMouse->icon) {
                case CHOICES_BREAK_UP_BUTTON:
                        tAction = CHOICES_BREAK_DOWN_BUTTON;
                        break;
                case CHOICES_BREAK_DOWN_BUTTON:
                        tAction = CHOICES_BREAK_UP_BUTTON;
                        break;
                case CHOICES_SCALE_UP_BUTTON:
                        tAction = CHOICES_SCALE_DOWN_BUTTON;
                        break;
                case CHOICES_SCALE_DOWN_BUTTON:
                        tAction = CHOICES_SCALE_UP_BUTTON;
                        break;
                default:
                        break;
                }
        }

        /* Actions */
        bCloseWindow = FALSE;
        switch (tAction) {
        case CHOICES_DEFAULT_BUTTON:
                vDefaultButtonAction(pMouse->window);
                break;
        case CHOICES_SAVE_BUTTON:
                vSaveButtonAction();
                break;
        case CHOICES_CANCEL_BUTTON:
                bCloseWindow = TRUE;
                break;
        case CHOICES_APPLY_BUTTON:
                vApplyButtonAction();
                bCloseWindow = TRUE;
                break;
        case CHOICES_BREAK_BUTTON:
                vSetParagraphBreak(pMouse->window, DEFAULT_SCREEN_WIDTH);
                break;
        case CHOICES_BREAK_UP_BUTTON:
                vChangeParagraphBreak(pMouse->window, 1);
                break;
        case CHOICES_BREAK_DOWN_BUTTON:
                vChangeParagraphBreak(pMouse->window, -1);
                break;
        case CHOICES_NO_BREAK_BUTTON:
                vSetParagraphBreak(pMouse->window, 0);
                break;
        case CHOICES_AUTOFILETYPE_BUTTON:
                vChangeAutofiletype(pMouse->window);
                break;
        case CHOICES_HIDDEN_TEXT_BUTTON:
                vChangeHiddenText(pMouse->window);
                break;
        case CHOICES_WITH_IMAGES_BUTTON:
                vUseFontsImages(TRUE, TRUE);
                break;
        case CHOICES_NO_IMAGES_BUTTON:
                vUseFontsImages(TRUE, FALSE);
                break;
        case CHOICES_TEXTONLY_BUTTON:
                vUseFontsImages(FALSE, FALSE);
                break;
        case CHOICES_SCALE_UP_BUTTON:
                vChangeScaleFactor(pMouse->window, 5);
                break;
        case CHOICES_SCALE_DOWN_BUTTON:
                vChangeScaleFactor(pMouse->window, -5);
                break;
        default:
                DBG_DEC(pMouse->icon);
                break;
        }
        if (bCloseWindow) {
                Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
        }
        return TRUE;
} /* end of bChoicesMouseClick */

/*
 * bChoicesKeyPressed - handle a key in the Choices window
 */
BOOL
bChoicesKeyPressed(event_pollblock *pEvent, void *pvReference)
{
        icon_block      tIcon;
        caret_block     *pCaret;
        char            *pcChar;
        int             iNumber;

        DBG_MSG("bChoicesKeyPressed");

        fail(pEvent == NULL);
        fail(pEvent->type != event_KEY);

        if (pEvent->data.key.code != '\r') {
                Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
                return TRUE;
        }

        pCaret = &pEvent->data.key.caret;

        Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
        if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
                werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
        }
        iNumber = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);

        switch(pCaret->icon) {
        case CHOICES_BREAK_WRITEABLE:
                if (*pcChar != '\0' && *pcChar != '\r') {
                        DBG_DEC(*pcChar);
                        iNumber = DEFAULT_SCREEN_WIDTH;
                } else if (iNumber < MIN_SCREEN_WIDTH) {
                        iNumber = MIN_SCREEN_WIDTH;
                } else if (iNumber > MAX_SCREEN_WIDTH) {
                        iNumber = MAX_SCREEN_WIDTH;
                }
                vSetParagraphBreak(pCaret->window, iNumber);
                break;
        case CHOICES_SCALE_WRITEABLE:
                if (*pcChar != '\0' && *pcChar != '\r') {
                        DBG_DEC(*pcChar);
                        iNumber = DEFAULT_SCALE_FACTOR;
                } else if (iNumber < MIN_SCALE_FACTOR) {
                        iNumber = MIN_SCALE_FACTOR;
                } else if (iNumber > MAX_SCALE_FACTOR) {
                        iNumber = MAX_SCALE_FACTOR;
                }
                vSetScaleFactor(pCaret->window, iNumber);
                break;
        default:
                DBG_DEC(pCaret->icon);
                break;
        }
        return TRUE;
} /* end of bChoicesKeyPressed */
#endif /* __riscos */