xref: /plan9/sys/src/cmd/aux/antiword/options.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1 /*
2  * options.c
3  * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
4  *
5  * Description:
6  * Read and write the options
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #if defined(__riscos)
13 #include "DeskLib:Error.h"
14 #include "DeskLib:Wimp.h"
15 #else
16 #include <stdlib.h>
17 #if defined(__dos) || defined(N_PLAT_NLM)
18 extern int getopt(int, char **, const char *);
19 #else
20 #include <unistd.h>
21 #endif /* __dos */
22 #endif /* __riscos */
23 #include "antiword.h"
24 
25 #if defined(__riscos)
26 #define PARAGRAPH_BREAK		"set paragraph_break=%d"
27 #define AUTOFILETYPE		"set autofiletype_allowed=%d"
28 #define USE_OUTLINEFONTS	"set use_outlinefonts=%d"
29 #define SHOW_IMAGES		"set show_images=%d"
30 #define HIDE_HIDDEN_TEXT	"set hide_hidden_text=%d"
31 #define SCALE_FACTOR_START	"set scale_factor_start=%d"
32 #else
33 #define LEAFNAME_SIZE		(32+1)
34 #endif /* __riscos */
35 
36 /* Current values for options */
37 static options_type	tOptionsCurr;
38 #if defined(__riscos)
39 /* Temporary values for options */
40 static options_type	tOptionsTemp;
41 #else
42 typedef struct papersize_tag {
43 	char	szName[16];	/* Papersize name */
44 	USHORT	usWidth;	/* In points */
45 	USHORT	usHeight;	/* In points */
46 } papersize_type;
47 
48 static const papersize_type atPaperSizes[] = {
49 	{	"10x14",	 720,	1008	},
50 	{	"a3",		 842,	1191	},
51 	{	"a4",		 595,	 842	},
52 	{	"a5",		 420,	 595	},
53 	{	"b4",		 729,	1032	},
54 	{	"b5",		 516,	 729	},
55 	{	"executive",	 540,	 720	},
56 	{	"folio",	 612,	 936	},
57 	{	"legal",	 612,	1008	},
58 	{	"letter",	 612,	 792	},
59 	{	"note",		 540,	 720	},
60 	{	"quarto",	 610,	 780	},
61 	{	"statement",	 396,	 612	},
62 	{	"tabloid",	 792,	1224	},
63 	{	"",		   0,	   0	},
64 };
65 #endif /* __riscos */
66 /* Default values for options */
67 static const options_type	tOptionsDefault = {
68 	DEFAULT_SCREEN_WIDTH,
69 #if defined(__riscos)
70 	conversion_draw,
71 #else
72 	conversion_text,
73 #endif /* __riscos */
74 	TRUE,
75 	TRUE,
76 	FALSE,
77 	encoding_latin_1,
78 	INT_MAX,
79 	INT_MAX,
80 	level_default,
81 #if defined(__riscos)
82 	TRUE,
83 	DEFAULT_SCALE_FACTOR,
84 #endif /* __riscos */
85 };
86 
87 
88 #if !defined(__riscos)
89 /*
90  * bCorrectPapersize - see if the papersize is correct
91  *
92  * TRUE if the papersize is correct, otherwise FALSE
93  */
94 static BOOL
bCorrectPapersize(const char * szName,conversion_type eConversionType)95 bCorrectPapersize(const char *szName, conversion_type eConversionType)
96 {
97 	const papersize_type	*pPaperSize;
98 
99 	for (pPaperSize = atPaperSizes;
100 	     pPaperSize->szName[0] != '\0';
101 	     pPaperSize++) {
102 		if (!STRCEQ(pPaperSize->szName,  szName)) {
103 			continue;
104 		}
105 		DBG_DEC(pPaperSize->usWidth);
106 		DBG_DEC(pPaperSize->usHeight);
107 		tOptionsCurr.eConversionType = eConversionType;
108 		tOptionsCurr.iPageHeight = (int)pPaperSize->usHeight;
109 		tOptionsCurr.iPageWidth = (int)pPaperSize->usWidth;
110 		return TRUE;
111 	}
112 	return FALSE;
113 } /* end of bCorrectPapersize */
114 
115 /*
116  * szCreateSuffix - create a suffix for the file
117  *
118  * Returns the suffix
119  */
120 static const char *
szCreateSuffix(const char * szLeafname)121 szCreateSuffix(const char *szLeafname)
122 {
123 	const char	*pcDot;
124 
125 	pcDot = strrchr(szLeafname, '.');
126 	if (pcDot != NULL && STRCEQ(pcDot, ".txt")) {
127 		/* There is already a .txt suffix, no need for another one */
128 		return "";
129 	}
130 	return ".txt";
131 } /* end of szCreateSuffix */
132 
133 /*
134  * eMappingFile2Encoding - convert the mapping file to an encoding
135  */
136 static encoding_type
eMappingFile2Encoding(const char * szLeafname)137 eMappingFile2Encoding(const char *szLeafname)
138 {
139 	char	szMappingFile[LEAFNAME_SIZE+4];
140 
141 	fail(szLeafname == NULL);
142 
143 	if (strlen(szLeafname) + 4 >= sizeof(szMappingFile)) {
144 		DBG_MSG(szLeafname);
145 		return encoding_latin_1;
146 	}
147 
148 	sprintf(szMappingFile, "%s%s", szLeafname, szCreateSuffix(szLeafname));
149 
150 	DBG_MSG(szMappingFile);
151 
152 	if (STRCEQ(szMappingFile, MAPPING_FILE_UTF_8)) {
153 		return encoding_utf_8;
154 	}
155 	if (STRCEQ(szMappingFile, MAPPING_FILE_CP852) ||
156 	    STRCEQ(szMappingFile, MAPPING_FILE_CP1250) ||
157 	    STRCEQ(szMappingFile, MAPPING_FILE_8859_2)) {
158 		return encoding_latin_2;
159 	}
160 	if (STRCEQ(szMappingFile, MAPPING_FILE_KOI8_R) ||
161 	    STRCEQ(szMappingFile, MAPPING_FILE_KOI8_U) ||
162 	    STRCEQ(szMappingFile, MAPPING_FILE_CP866) ||
163 	    STRCEQ(szMappingFile, MAPPING_FILE_CP1251) ||
164 	    STRCEQ(szMappingFile, MAPPING_FILE_8859_5)) {
165 		return encoding_cyrillic;
166 	}
167 	return encoding_latin_1;
168 } /* end of eMappingFile2Encoding */
169 #endif /* !__riscos */
170 
171 /*
172  * pOpenCharacterMappingFile - open the mapping file
173  *
174  * Returns the file pointer or NULL
175  */
176 static FILE *
pOpenCharacterMappingFile(const char * szLeafname)177 pOpenCharacterMappingFile(const char *szLeafname)
178 {
179 #if !defined(__riscos)
180 	FILE	*pFile;
181 	const char	*szHome, *szAntiword, *szSuffix;
182 	size_t	tFilenameLen;
183 	char	szMappingFile[PATH_MAX+1];
184 #endif /* !__riscos */
185 
186 	if (szLeafname == NULL || szLeafname[0] == '\0') {
187 		return NULL;
188 	}
189 
190 	DBG_MSG(szLeafname);
191 
192 #if defined(__riscos)
193 	return fopen(szLeafname, "r");
194 #else
195 	/* Set the suffix */
196 	szSuffix = szCreateSuffix(szLeafname);
197 
198 	/* Set length */
199 	tFilenameLen = strlen(szLeafname) + strlen(szSuffix);
200 
201 	/* Try the environment version of the mapping file */
202 	szAntiword = szGetAntiwordDirectory();
203 	if (szAntiword != NULL && szAntiword[0] != '\0') {
204 	    if (strlen(szAntiword) + tFilenameLen <
205 		sizeof(szMappingFile) -
206 		sizeof(FILE_SEPARATOR)) {
207 			sprintf(szMappingFile,
208 				"%s" FILE_SEPARATOR "%s%s",
209 				szAntiword, szLeafname, szSuffix);
210 			DBG_MSG(szMappingFile);
211 			pFile = fopen(szMappingFile, "r");
212 			if (pFile != NULL) {
213 				return pFile;
214 			}
215 		} else {
216 			werr(0, "Environment mappingfilename ignored");
217 		}
218 	}
219 
220 	/* Try the local version of the mapping file */
221 	szHome = szGetHomeDirectory();
222 	if (strlen(szHome) + tFilenameLen <
223 	    sizeof(szMappingFile) -
224 	    sizeof(ANTIWORD_DIR) -
225 	    2 * sizeof(FILE_SEPARATOR)) {
226 		sprintf(szMappingFile,
227 			"%s" FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR "%s%s",
228 			szHome, szLeafname, szSuffix);
229 		DBG_MSG(szMappingFile);
230 		pFile = fopen(szMappingFile, "r");
231 		if (pFile != NULL) {
232 			return pFile;
233 		}
234 	} else {
235 		werr(0, "Local mappingfilename too long, ignored");
236 	}
237 
238 	/* Try the global version of the mapping file */
239 	if (tFilenameLen <
240 	    sizeof(szMappingFile) -
241 	    sizeof(GLOBAL_ANTIWORD_DIR) -
242 	    sizeof(FILE_SEPARATOR)) {
243 		sprintf(szMappingFile,
244 			GLOBAL_ANTIWORD_DIR FILE_SEPARATOR "%s%s",
245 			szLeafname, szSuffix);
246 		DBG_MSG(szMappingFile);
247 		pFile = fopen(szMappingFile, "r");
248 		if (pFile != NULL) {
249 			return pFile;
250 		}
251 	} else {
252 		werr(0, "Global mappingfilename too long, ignored");
253 	}
254 	werr(0, "I can't open your mapping file (%s%s)\n"
255 		"It is not in '%s" FILE_SEPARATOR ANTIWORD_DIR "' nor in '"
256 		GLOBAL_ANTIWORD_DIR "'.", szLeafname, szSuffix, szHome);
257 	return NULL;
258 #endif /* __riscos */
259 } /* end of pOpenCharacterMappingFile */
260 
261 /*
262  * vCloseCharacterMappingFile - close the mapping file
263  */
264 static void
vCloseCharacterMappingFile(FILE * pFile)265 vCloseCharacterMappingFile(FILE *pFile)
266 {
267 	(void)fclose(pFile);
268 } /* end of pCloseCharacterMappingFile */
269 
270 
271 /*
272  * iReadOptions - read options
273  *
274  * returns:	-1: error
275  *		 0: help
276  *		>0: index first file argument
277  */
278 int
iReadOptions(int argc,char ** argv)279 iReadOptions(int argc, char **argv)
280 {
281 #if defined(__riscos)
282 	FILE	*pFile;
283 	const char	*szAlphabet;
284 	int	iAlphabet;
285 	char	szLine[81];
286 #else
287 	extern	char	*optarg;
288 	extern int	optind;
289 	char	*pcChar, *szTmp;
290 	int	iChar;
291 	char	szLeafname[LEAFNAME_SIZE];
292 #endif /* __riscos */
293 	FILE	*pCharacterMappingFile;
294 	int	iTmp;
295 	BOOL	bSuccess;
296 
297 	DBG_MSG("iReadOptions");
298 
299 /* Defaults */
300 	tOptionsCurr = tOptionsDefault;
301 
302 #if defined(__riscos)
303 /* Choices file */
304 	pFile = fopen("<AntiWord$ChoicesFile>", "r");
305 	DBG_MSG_C(pFile == NULL, "Choices file not found");
306 	DBG_HEX_C(pFile != NULL, pFile);
307 	if (pFile != NULL) {
308 		while (fgets(szLine, (int)sizeof(szLine), pFile) != NULL) {
309 			DBG_MSG(szLine);
310 			if (szLine[0] == '#' ||
311 			    szLine[0] == '\r' ||
312 			    szLine[0] == '\n') {
313 				continue;
314 			}
315 			if (sscanf(szLine, PARAGRAPH_BREAK, &iTmp) == 1 &&
316 			    (iTmp == 0 ||
317 			    (iTmp >= MIN_SCREEN_WIDTH &&
318 			     iTmp <= MAX_SCREEN_WIDTH))) {
319 				tOptionsCurr.iParagraphBreak = iTmp;
320 				DBG_DEC(tOptionsCurr.iParagraphBreak);
321 			} else if (sscanf(szLine, AUTOFILETYPE, &iTmp)
322 								== 1) {
323 				tOptionsCurr.bAutofiletypeAllowed =
324 								iTmp != 0;
325 				DBG_DEC(tOptionsCurr.bAutofiletypeAllowed);
326 			} else if (sscanf(szLine, USE_OUTLINEFONTS, &iTmp)
327 								== 1) {
328 				tOptionsCurr.eConversionType =
329 					iTmp == 0 ?
330 					conversion_text : conversion_draw;
331 				DBG_DEC(tOptionsCurr.eConversionType);
332 			} else if (sscanf(szLine, SHOW_IMAGES, &iTmp)
333 								== 1) {
334 				tOptionsCurr.eImageLevel = iTmp != 0 ?
335 					level_default : level_no_images;
336 			} else if (sscanf(szLine, HIDE_HIDDEN_TEXT, &iTmp)
337 								== 1) {
338 				tOptionsCurr.bHideHiddenText = iTmp != 0;
339 				DBG_DEC(tOptionsCurr.bHideHiddenText);
340 			} else if (sscanf(szLine, SCALE_FACTOR_START, &iTmp)
341 								== 1) {
342 				if (iTmp >= MIN_SCALE_FACTOR &&
343 				    iTmp <= MAX_SCALE_FACTOR) {
344 					tOptionsCurr.iScaleFactor = iTmp;
345 					DBG_DEC(tOptionsCurr.iScaleFactor);
346 				}
347 			}
348 		}
349 		(void)fclose(pFile);
350 	}
351 	iAlphabet = iReadCurrentAlphabetNumber();
352 	switch (iAlphabet) {
353 	case 101:	/* ISO-8859-1 aka Latin1 */
354 		szAlphabet = "<AntiWord$Latin1>";
355 		break;
356 	case 112:	/* ISO-8859-15 aka Latin9 */
357 		szAlphabet = "<AntiWord$Latin9>";
358 		break;
359 	default:
360 		werr(0, "Alphabet '%d' is not supported", iAlphabet);
361 		return -1;
362 	}
363 	pCharacterMappingFile = pOpenCharacterMappingFile(szAlphabet);
364 	if (pCharacterMappingFile != NULL) {
365 		bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
366 		vCloseCharacterMappingFile(pCharacterMappingFile);
367 	} else {
368 		bSuccess = FALSE;
369 	}
370 	return bSuccess ? 1 : -1;
371 #else
372 /* Environment */
373 	szTmp = getenv("COLUMNS");
374 	if (szTmp != NULL) {
375 		DBG_MSG(szTmp);
376 		iTmp = (int)strtol(szTmp, &pcChar, 10);
377 		if (*pcChar == '\0') {
378 			iTmp -= 4;	/* This is for the edge */
379 			if (iTmp < MIN_SCREEN_WIDTH) {
380 				iTmp = MIN_SCREEN_WIDTH;
381 			} else if (iTmp > MAX_SCREEN_WIDTH) {
382 				iTmp = MAX_SCREEN_WIDTH;
383 			}
384 			tOptionsCurr.iParagraphBreak = iTmp;
385 			DBG_DEC(tOptionsCurr.iParagraphBreak);
386 		}
387 	}
388 	strncpy(szLeafname, szGetDefaultMappingFile(), sizeof(szLeafname) - 1);
389 	szLeafname[sizeof(szLeafname) - 1] = '\0';
390 /* Command line */
391 	while ((iChar = getopt(argc, argv, "La:fhi:m:p:rstw:x:")) != -1) {
392 		switch (iChar) {
393 		case 'L':
394 			tOptionsCurr.bUseLandscape = TRUE;
395 			break;
396 		case 'a':
397 			if (!bCorrectPapersize(optarg, conversion_pdf)) {
398 				werr(0, "-a without a valid papersize");
399 				return -1;
400 			}
401 			break;
402 		case 'f':
403 			tOptionsCurr.eConversionType = conversion_fmt_text;
404 			break;
405 		case 'h':
406 			return 0;
407 		case 'i':
408 			iTmp = (int)strtol(optarg, &pcChar, 10);
409 			if (*pcChar != '\0') {
410 				break;
411 			}
412 			switch (iTmp) {
413 			case 0:
414 				tOptionsCurr.eImageLevel = level_gs_special;
415 				break;
416 			case 1:
417 				tOptionsCurr.eImageLevel = level_no_images;
418 				break;
419 			case 2:
420 				tOptionsCurr.eImageLevel = level_ps_2;
421 				break;
422 			case 3:
423 				tOptionsCurr.eImageLevel = level_ps_3;
424 				break;
425 			default:
426 				tOptionsCurr.eImageLevel = level_default;
427 				break;
428 			}
429 			DBG_DEC(tOptionsCurr.eImageLevel);
430 			break;
431 		case 'm':
432 			if (tOptionsCurr.eConversionType == conversion_xml) {
433 				werr(0, "XML doesn't need a mapping file");
434 				break;
435 			}
436 			strncpy(szLeafname, optarg, sizeof(szLeafname) - 1);
437 			szLeafname[sizeof(szLeafname) - 1] = '\0';
438 			DBG_MSG(szLeafname);
439 			break;
440 		case 'p':
441 			if (!bCorrectPapersize(optarg, conversion_ps)) {
442 				werr(0, "-p without a valid papersize");
443 				return -1;
444 			}
445 			break;
446 		case 'r':
447 			tOptionsCurr.bRemoveRemovedText = FALSE;
448 			break;
449 		case 's':
450 			tOptionsCurr.bHideHiddenText = FALSE;
451 			break;
452 		case 't':
453 			tOptionsCurr.eConversionType = conversion_text;
454 			break;
455 		case 'w':
456 			iTmp = (int)strtol(optarg, &pcChar, 10);
457 			if (*pcChar == '\0') {
458 				if (iTmp != 0 && iTmp < MIN_SCREEN_WIDTH) {
459 					iTmp = MIN_SCREEN_WIDTH;
460 				} else if (iTmp > MAX_SCREEN_WIDTH) {
461 					iTmp = MAX_SCREEN_WIDTH;
462 				}
463 				tOptionsCurr.iParagraphBreak = iTmp;
464 				DBG_DEC(tOptionsCurr.iParagraphBreak);
465 			}
466 			break;
467 		case 'x':
468 			if (STREQ(optarg, "db")) {
469 				tOptionsCurr.iParagraphBreak = 0;
470 				tOptionsCurr.eConversionType = conversion_xml;
471 				strcpy(szLeafname, MAPPING_FILE_UTF_8);
472 			} else {
473 				werr(0, "-x %s is not supported", optarg);
474 				return -1;
475 			}
476 			break;
477 		default:
478 			return -1;
479 		}
480 	}
481 
482 	tOptionsCurr.eEncoding = eMappingFile2Encoding(szLeafname);
483 	DBG_DEC(tOptionsCurr.eEncoding);
484 
485 	if (tOptionsCurr.eConversionType == conversion_ps &&
486 	    tOptionsCurr.eEncoding == encoding_utf_8) {
487 		werr(0,
488 		"The combination PostScript and UTF-8 is not supported");
489 		return -1;
490 	}
491 
492 	if (tOptionsCurr.eConversionType == conversion_pdf &&
493 	    tOptionsCurr.eEncoding == encoding_utf_8) {
494 		werr(0,
495 		"The combination PDF and UTF-8 is not supported");
496 		return -1;
497 	}
498 
499 	if (tOptionsCurr.eConversionType == conversion_pdf &&
500 	    tOptionsCurr.eEncoding == encoding_cyrillic) {
501 		werr(0,
502 		"The combination PDF and Cyrillic is not supported");
503 		return -1;
504 	}
505 
506 	if (tOptionsCurr.eConversionType == conversion_ps ||
507 	    tOptionsCurr.eConversionType == conversion_pdf) {
508 		/* PostScript or PDF mode */
509 		if (tOptionsCurr.bUseLandscape) {
510 			/* Swap the page height and width */
511 			iTmp = tOptionsCurr.iPageHeight;
512 			tOptionsCurr.iPageHeight = tOptionsCurr.iPageWidth;
513 			tOptionsCurr.iPageWidth = iTmp;
514 		}
515 		/* The paragraph break depends on the width of the paper */
516 		tOptionsCurr.iParagraphBreak = iMilliPoints2Char(
517 			(long)tOptionsCurr.iPageWidth * 1000 -
518 			lDrawUnits2MilliPoints(
519 				PS_LEFT_MARGIN + PS_RIGHT_MARGIN));
520 		DBG_DEC(tOptionsCurr.iParagraphBreak);
521 	}
522 
523 	pCharacterMappingFile = pOpenCharacterMappingFile(szLeafname);
524 	if (pCharacterMappingFile != NULL) {
525 		bSuccess = bReadCharacterMappingTable(pCharacterMappingFile);
526 		vCloseCharacterMappingFile(pCharacterMappingFile);
527 	} else {
528 		bSuccess = FALSE;
529 	}
530 	return bSuccess ? optind : -1;
531 #endif /* __riscos */
532 } /* end of iReadOptions */
533 
534 /*
535  * vGetOptions - get a copy of the current option values
536  */
537 void
vGetOptions(options_type * pOptions)538 vGetOptions(options_type *pOptions)
539 {
540 	fail(pOptions == NULL);
541 
542 	*pOptions = tOptionsCurr;
543 } /* end of vGetOptions */
544 
545 #if defined(__riscos)
546 /*
547  * vWriteOptions - write the current options to the Options file
548  */
549 static void
vWriteOptions(void)550 vWriteOptions(void)
551 {
552 	FILE	*pFile;
553 	char	*szOptionsFile;
554 
555 	TRACE_MSG("vWriteOptions");
556 
557 	szOptionsFile = getenv("AntiWord$ChoicesSave");
558 	if (szOptionsFile == NULL) {
559 		werr(0, "Warning: Name of the Choices file not found");
560 		return;
561 	}
562 	if (!bMakeDirectory(szOptionsFile)) {
563 		werr(0,
564 		"Warning: I can't make a directory for the Choices file");
565 		return;
566 	}
567 	pFile = fopen(szOptionsFile, "w");
568 	if (pFile == NULL) {
569 		werr(0, "Warning: I can't write the Choices file");
570 		return;
571 	}
572 	(void)fprintf(pFile, PARAGRAPH_BREAK"\n",
573 		tOptionsCurr.iParagraphBreak);
574 	(void)fprintf(pFile, AUTOFILETYPE"\n",
575 		tOptionsCurr.bAutofiletypeAllowed);
576 	(void)fprintf(pFile, USE_OUTLINEFONTS"\n",
577 		tOptionsCurr.eConversionType == conversion_text ? 0 : 1);
578 	(void)fprintf(pFile, SHOW_IMAGES"\n",
579 		tOptionsCurr.eImageLevel == level_no_images ? 0 : 1);
580 	(void)fprintf(pFile, HIDE_HIDDEN_TEXT"\n",
581 		tOptionsCurr.bHideHiddenText);
582 	(void)fprintf(pFile, SCALE_FACTOR_START"\n",
583 		tOptionsCurr.iScaleFactor);
584 	(void)fclose(pFile);
585 } /* end of vWriteOptions */
586 
587 /*
588  * vChoicesOpenAction - action to be taken when the Choices window opens
589  */
590 void
vChoicesOpenAction(window_handle tWindow)591 vChoicesOpenAction(window_handle tWindow)
592 {
593 	TRACE_MSG("vChoicesOpenAction");
594 
595 	tOptionsTemp = tOptionsCurr;
596 	if (tOptionsTemp.iParagraphBreak == 0) {
597 		vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, FALSE);
598 		vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, TRUE);
599 		vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
600 					DEFAULT_SCREEN_WIDTH);
601 	} else {
602 		vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
603 		vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
604 		vUpdateWriteableNumber(tWindow,
605 			CHOICES_BREAK_WRITEABLE,
606 			tOptionsTemp.iParagraphBreak);
607 	}
608 	vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
609 					tOptionsTemp.bAutofiletypeAllowed);
610 	vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
611 					tOptionsTemp.bHideHiddenText);
612 	if (tOptionsTemp.eConversionType == conversion_draw) {
613 		vUpdateRadioButton(tWindow,
614 			CHOICES_WITH_IMAGES_BUTTON,
615 			tOptionsTemp.eImageLevel != level_no_images);
616 		vUpdateRadioButton(tWindow,
617 			CHOICES_NO_IMAGES_BUTTON,
618 			tOptionsTemp.eImageLevel == level_no_images);
619 		vUpdateRadioButton(tWindow,
620 			CHOICES_TEXTONLY_BUTTON, FALSE);
621 	} else {
622 		vUpdateRadioButton(tWindow,
623 			CHOICES_WITH_IMAGES_BUTTON, FALSE);
624 		vUpdateRadioButton(tWindow,
625 			CHOICES_NO_IMAGES_BUTTON, FALSE);
626 		vUpdateRadioButton(tWindow,
627 			CHOICES_TEXTONLY_BUTTON, TRUE);
628 	}
629 	vUpdateWriteableNumber(tWindow,
630 		CHOICES_SCALE_WRITEABLE, tOptionsTemp.iScaleFactor);
631 	TRACE_MSG("end of vChoicesOpenAction");
632 } /* end of vChoicesOpenAction */
633 
634 /*
635  * vDefaultButtonAction - action when the default button is clicked
636  */
637 static void
vDefaultButtonAction(window_handle tWindow)638 vDefaultButtonAction(window_handle tWindow)
639 {
640 	TRACE_MSG("vDefaultButtonAction");
641 
642 	tOptionsTemp = tOptionsDefault;
643 	vUpdateRadioButton(tWindow, CHOICES_BREAK_BUTTON, TRUE);
644 	vUpdateRadioButton(tWindow, CHOICES_NO_BREAK_BUTTON, FALSE);
645 	vUpdateWriteableNumber(tWindow, CHOICES_BREAK_WRITEABLE,
646 			tOptionsTemp.iParagraphBreak);
647 	vUpdateRadioButton(tWindow, CHOICES_AUTOFILETYPE_BUTTON,
648 			tOptionsTemp.bAutofiletypeAllowed);
649 	vUpdateRadioButton(tWindow, CHOICES_HIDDEN_TEXT_BUTTON,
650 			tOptionsTemp.bHideHiddenText);
651 	vUpdateRadioButton(tWindow, CHOICES_WITH_IMAGES_BUTTON,
652 			tOptionsTemp.eConversionType == conversion_draw &&
653 			tOptionsTemp.eImageLevel != level_no_images);
654 	vUpdateRadioButton(tWindow, CHOICES_NO_IMAGES_BUTTON,
655 			tOptionsTemp.eConversionType == conversion_draw &&
656 			tOptionsTemp.eImageLevel == level_no_images);
657 	vUpdateRadioButton(tWindow, CHOICES_TEXTONLY_BUTTON,
658 			tOptionsTemp.eConversionType == conversion_text);
659 	vUpdateWriteableNumber(tWindow, CHOICES_SCALE_WRITEABLE,
660 			tOptionsTemp.iScaleFactor);
661 } /* end of vDefaultButtonAction */
662 
663 /*
664  * vApplyButtonAction - action to be taken when the OK button is clicked
665  */
666 static void
vApplyButtonAction(void)667 vApplyButtonAction(void)
668 {
669 	TRACE_MSG("vApplyButtonAction");
670 
671 	tOptionsCurr = tOptionsTemp;
672 } /* end of vApplyButtonAction */
673 
674 /*
675  * vSaveButtonAction - action to be taken when the save button is clicked
676  */
677 static void
vSaveButtonAction(void)678 vSaveButtonAction(void)
679 {
680 	TRACE_MSG("vSaveButtonAction");
681 
682 	vApplyButtonAction();
683 	vWriteOptions();
684 } /* end of vSaveButtonAction */
685 
686 /*
687  * vSetParagraphBreak - set the paragraph break to the given number
688  */
689 static void
vSetParagraphBreak(window_handle tWindow,int iNumber)690 vSetParagraphBreak(window_handle tWindow, int iNumber)
691 {
692 	tOptionsTemp.iParagraphBreak = iNumber;
693 	if (tOptionsTemp.iParagraphBreak == 0) {
694 		return;
695 	}
696 	vUpdateWriteableNumber(tWindow,
697 			CHOICES_BREAK_WRITEABLE,
698 			tOptionsTemp.iParagraphBreak);
699 } /* end of vSetParagraphBreak */
700 
701 /*
702  * vChangeParagraphBreak - change the paragraph break with the given number
703  */
704 static void
vChangeParagraphBreak(window_handle tWindow,int iNumber)705 vChangeParagraphBreak(window_handle tWindow, int iNumber)
706 {
707 	int	iTmp;
708 
709 	iTmp = tOptionsTemp.iParagraphBreak + iNumber;
710 	if (iTmp < MIN_SCREEN_WIDTH || iTmp > MAX_SCREEN_WIDTH) {
711 	  	/* Ignore */
712 		return;
713 	}
714 	tOptionsTemp.iParagraphBreak = iTmp;
715 	vUpdateWriteableNumber(tWindow,
716 			CHOICES_BREAK_WRITEABLE,
717 			tOptionsTemp.iParagraphBreak);
718 } /* end of vChangeParagraphBreak */
719 
720 /*
721  * vChangeAutofiletype - invert the permission to autofiletype
722  */
723 static void
vChangeAutofiletype(window_handle tWindow)724 vChangeAutofiletype(window_handle tWindow)
725 {
726 	tOptionsTemp.bAutofiletypeAllowed =
727 				!tOptionsTemp.bAutofiletypeAllowed;
728 	vUpdateRadioButton(tWindow,
729 			CHOICES_AUTOFILETYPE_BUTTON,
730 			tOptionsTemp.bAutofiletypeAllowed);
731 } /* end of vChangeAutofiletype */
732 
733 /*
734  * vChangeHiddenText - invert the hide/show hidden text
735  */
736 static void
vChangeHiddenText(window_handle tWindow)737 vChangeHiddenText(window_handle tWindow)
738 {
739 	tOptionsTemp.bHideHiddenText = !tOptionsTemp.bHideHiddenText;
740 	vUpdateRadioButton(tWindow,
741 			CHOICES_HIDDEN_TEXT_BUTTON,
742 			tOptionsTemp.bHideHiddenText);
743 } /* end of vChangeHiddenText */
744 
745 /*
746  * vUseFontsImages - use outline fonts, show images
747  */
748 static void
vUseFontsImages(BOOL bUseOutlineFonts,BOOL bShowImages)749 vUseFontsImages(BOOL bUseOutlineFonts, BOOL bShowImages)
750 {
751 	tOptionsTemp.eConversionType =
752 		bUseOutlineFonts ? conversion_draw : conversion_text;
753 	tOptionsTemp.eImageLevel =
754 		bUseOutlineFonts && bShowImages ?
755 		level_default : level_no_images;
756 } /* end of vUseFontsImages */
757 
758 /*
759  * vSetScaleFactor - set the scale factor to the given number
760  */
761 static void
vSetScaleFactor(window_handle tWindow,int iNumber)762 vSetScaleFactor(window_handle tWindow, int iNumber)
763 {
764   	tOptionsTemp.iScaleFactor = iNumber;
765 	vUpdateWriteableNumber(tWindow,
766 			CHOICES_SCALE_WRITEABLE,
767 			tOptionsTemp.iScaleFactor);
768 } /* end of vSetScaleFactor */
769 
770 /*
771  * vChangeScaleFactor - change the scale factor with the given number
772  */
773 static void
vChangeScaleFactor(window_handle tWindow,int iNumber)774 vChangeScaleFactor(window_handle tWindow, int iNumber)
775 {
776 	int	iTmp;
777 
778 	iTmp = tOptionsTemp.iScaleFactor + iNumber;
779 	if (iTmp < MIN_SCALE_FACTOR || iTmp > MAX_SCALE_FACTOR) {
780 	  	/* Ignore */
781 		return;
782 	}
783 	tOptionsTemp.iScaleFactor = iTmp;
784 	vUpdateWriteableNumber(tWindow,
785 			CHOICES_SCALE_WRITEABLE,
786 			tOptionsTemp.iScaleFactor);
787 } /* end of vChangeScaleFactor */
788 
789 /*
790  * bChoicesMouseClick - handle a mouse click in the Choices window
791  */
792 BOOL
bChoicesMouseClick(event_pollblock * pEvent,void * pvReference)793 bChoicesMouseClick(event_pollblock *pEvent, void *pvReference)
794 {
795 	icon_handle	tAction;
796 	mouse_block	*pMouse;
797 	BOOL		bCloseWindow;
798 
799 	TRACE_MSG("bChoicesMouseClick");
800 
801 	fail(pEvent == NULL);
802 	fail(pEvent->type != event_CLICK);
803 
804 	pMouse = &pEvent->data.mouse;
805 	if (!pMouse->button.data.select && !pMouse->button.data.adjust) {
806 		/* Not handled here */
807 		DBG_HEX(pMouse->button.value);
808 		return FALSE;
809 	}
810 
811 	/* Which action should be taken */
812 	tAction = pMouse->icon;
813 	if (pMouse->button.data.adjust) {
814 	  	/* The adjust button reverses the direction */
815 		switch (pMouse->icon) {
816 		case CHOICES_BREAK_UP_BUTTON:
817 			tAction = CHOICES_BREAK_DOWN_BUTTON;
818 			break;
819 		case CHOICES_BREAK_DOWN_BUTTON:
820 			tAction = CHOICES_BREAK_UP_BUTTON;
821 			break;
822 		case CHOICES_SCALE_UP_BUTTON:
823 			tAction = CHOICES_SCALE_DOWN_BUTTON;
824 			break;
825 		case CHOICES_SCALE_DOWN_BUTTON:
826 			tAction = CHOICES_SCALE_UP_BUTTON;
827 			break;
828 		default:
829 			break;
830 		}
831 	}
832 
833 	/* Actions */
834 	bCloseWindow = FALSE;
835 	switch (tAction) {
836 	case CHOICES_DEFAULT_BUTTON:
837 		vDefaultButtonAction(pMouse->window);
838 		break;
839 	case CHOICES_SAVE_BUTTON:
840 		vSaveButtonAction();
841 		break;
842 	case CHOICES_CANCEL_BUTTON:
843 		bCloseWindow = TRUE;
844 		break;
845 	case CHOICES_APPLY_BUTTON:
846 		vApplyButtonAction();
847 		bCloseWindow = TRUE;
848 		break;
849 	case CHOICES_BREAK_BUTTON:
850 		vSetParagraphBreak(pMouse->window, DEFAULT_SCREEN_WIDTH);
851 		break;
852 	case CHOICES_BREAK_UP_BUTTON:
853 		vChangeParagraphBreak(pMouse->window, 1);
854 		break;
855 	case CHOICES_BREAK_DOWN_BUTTON:
856 		vChangeParagraphBreak(pMouse->window, -1);
857 		break;
858 	case CHOICES_NO_BREAK_BUTTON:
859 		vSetParagraphBreak(pMouse->window, 0);
860 		break;
861 	case CHOICES_AUTOFILETYPE_BUTTON:
862 		vChangeAutofiletype(pMouse->window);
863 		break;
864 	case CHOICES_HIDDEN_TEXT_BUTTON:
865 		vChangeHiddenText(pMouse->window);
866 		break;
867 	case CHOICES_WITH_IMAGES_BUTTON:
868 		vUseFontsImages(TRUE, TRUE);
869 		break;
870 	case CHOICES_NO_IMAGES_BUTTON:
871 		vUseFontsImages(TRUE, FALSE);
872 		break;
873 	case CHOICES_TEXTONLY_BUTTON:
874 		vUseFontsImages(FALSE, FALSE);
875 		break;
876 	case CHOICES_SCALE_UP_BUTTON:
877 		vChangeScaleFactor(pMouse->window, 5);
878 		break;
879 	case CHOICES_SCALE_DOWN_BUTTON:
880 		vChangeScaleFactor(pMouse->window, -5);
881 		break;
882 	default:
883 		DBG_DEC(pMouse->icon);
884 		break;
885 	}
886 	if (bCloseWindow) {
887 		Error_CheckFatal(Wimp_CloseWindow(pMouse->window));
888 	}
889 	return TRUE;
890 } /* end of bChoicesMouseClick */
891 
892 /*
893  * bChoicesKeyPressed - handle a key in the Choices window
894  */
895 BOOL
bChoicesKeyPressed(event_pollblock * pEvent,void * pvReference)896 bChoicesKeyPressed(event_pollblock *pEvent, void *pvReference)
897 {
898 	icon_block	tIcon;
899 	caret_block	*pCaret;
900 	char		*pcChar;
901 	int		iNumber;
902 
903 	DBG_MSG("bChoicesKeyPressed");
904 
905 	fail(pEvent == NULL);
906 	fail(pEvent->type != event_KEY);
907 
908 	if (pEvent->data.key.code != '\r') {
909 		Error_CheckFatal(Wimp_ProcessKey(pEvent->data.key.code));
910 		return TRUE;
911 	}
912 
913 	pCaret = &pEvent->data.key.caret;
914 
915 	Error_CheckFatal(Wimp_GetIconState(pCaret->window, pCaret->icon, &tIcon));
916 	if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) {
917 		werr(1, "Icon %d must be indirected text", (int)pCaret->icon);
918 	}
919 	iNumber = (int)strtol(tIcon.data.indirecttext.buffer, &pcChar, 10);
920 
921 	switch(pCaret->icon) {
922 	case CHOICES_BREAK_WRITEABLE:
923 		if (*pcChar != '\0' && *pcChar != '\r') {
924 			DBG_DEC(*pcChar);
925 			iNumber = DEFAULT_SCREEN_WIDTH;
926 		} else if (iNumber < MIN_SCREEN_WIDTH) {
927 			iNumber = MIN_SCREEN_WIDTH;
928 		} else if (iNumber > MAX_SCREEN_WIDTH) {
929 			iNumber = MAX_SCREEN_WIDTH;
930 		}
931 		vSetParagraphBreak(pCaret->window, iNumber);
932 		break;
933 	case CHOICES_SCALE_WRITEABLE:
934 		if (*pcChar != '\0' && *pcChar != '\r') {
935 			DBG_DEC(*pcChar);
936 			iNumber = DEFAULT_SCALE_FACTOR;
937 		} else if (iNumber < MIN_SCALE_FACTOR) {
938 			iNumber = MIN_SCALE_FACTOR;
939 		} else if (iNumber > MAX_SCALE_FACTOR) {
940 			iNumber = MAX_SCALE_FACTOR;
941 		}
942 		vSetScaleFactor(pCaret->window, iNumber);
943 		break;
944 	default:
945 		DBG_DEC(pCaret->icon);
946 		break;
947 	}
948 	return TRUE;
949 } /* end of bChoicesKeyPressed */
950 #endif /* __riscos */
951