xref: /plan9/sys/src/cmd/aux/antiword/main_ros.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1 /*
2  * main_ros.c
3  *
4  * Released under GPL
5  *
6  * Copyright (C) 1998-2005 A.J. van Os
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * Description:
23  * The main program of !Antiword (RISC OS version)
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "DeskLib:Dialog2.h"
30 #include "DeskLib:Error.h"
31 #include "DeskLib:Event.h"
32 #include "DeskLib:EventMsg.h"
33 #include "DeskLib:Handler.h"
34 #include "DeskLib:Menu.h"
35 #include "DeskLib:Resource.h"
36 #include "DeskLib:Screen.h"
37 #include "DeskLib:Template.h"
38 #include "DeskLib:Window.h"
39 #if defined(__GNUC__)
40 #include "flexlib:flex.h"
41 #endif /* __GNUC__ */
42 #include "version.h"
43 #include "antiword.h"
44 
45 
46 /* The name of this program */
47 static char	*szTask = "!Antiword";
48 
49 /* The window handle of the choices window */
50 static window_handle	tChoicesWindow = 0;
51 
52 /* Dummy diagram with the iconbar menu pointer */
53 static diagram_type	tDummyDiagram;
54 
55 /* Program information Box */
56 static dialog2_block	*pInfoBox = NULL;
57 
58 /* Info box fields */
59 #define PURPOSE_INFO_FIELD	2
60 #define AUTHOR_INFO_FIELD	3
61 #define VERSION_INFO_FIELD	4
62 #define STATUS_INFO_FIELD	5
63 
64 /* Iconbar menu fields */
65 #define ICONBAR_INFO_FIELD	0
66 #define ICONBAR_CHOICES_FIELD	1
67 #define ICONBAR_QUIT_FIELD	2
68 
69 
70 /*
71  * bBarInfo - Show iconbar information
72  */
73 static BOOL
bBarInfo(event_pollblock * pEvent,void * pvReference)74 bBarInfo(event_pollblock *pEvent, void *pvReference)
75 {
76 	diagram_type	*pDiag;
77 
78 	TRACE_MSG("bBarInfo");
79 
80 	fail(pEvent == NULL);
81 	fail(pEvent->type != event_SEND);
82 	fail(pEvent->data.message.header.action != message_MENUWARN);
83 	fail(pvReference == NULL);
84 
85 	pDiag = (diagram_type *)pvReference;
86 
87 	if (menu_currentopen != pDiag->pSaveMenu ||
88 	    pEvent->data.message.data.menuwarn.selection[0] != ICONBAR_INFO_FIELD) {
89 		return FALSE;
90 	}
91 
92 	Dialog2_OpenDialogMenuLeaf(pEvent, pInfoBox);
93 	return TRUE;
94 } /* end of bBarInfo */
95 
96 /*
97  * vBarInfoSetText - Set the iconbar infobox text
98  */
99 static void
vBarInfoSetText(dialog2_block * pBox)100 vBarInfoSetText(dialog2_block *pBox)
101 {
102 	TRACE_MSG("vBarInfoSetText");
103 
104 	fail(pBox == NULL);
105 	fail(pBox != pInfoBox);
106 
107 	Icon_SetText(pBox->window, PURPOSE_INFO_FIELD, PURPOSESTRING);
108 	Icon_SetText(pBox->window, AUTHOR_INFO_FIELD, AUTHORSTRING);
109 	Icon_SetText(pBox->window, VERSION_INFO_FIELD, VERSIONSTRING);
110 	Icon_SetText(pBox->window, STATUS_INFO_FIELD, STATUSSTRING);
111 } /* end of vBarInfoSetText */
112 
113 /*
114  * bMouseButtonClick - respond to mouse button click
115  */
116 static BOOL
bMouseButtonClick(event_pollblock * pEvent,void * pvReference)117 bMouseButtonClick(event_pollblock *pEvent, void *pvReference)
118 {
119 	diagram_type	*pDiag;
120 	menu_ptr	pMenu;
121 	int		iPosY;
122 
123 	TRACE_MSG("bMouseButtonClick");
124 
125 	fail(pEvent == NULL);
126 	fail(pEvent->type != event_CLICK);
127 	fail(pvReference == NULL);
128 
129 	pDiag = (diagram_type *)pvReference;
130 
131 	if (pEvent->data.mouse.button.data.menu) {
132 		pMenu = pDiag->pSaveMenu;
133 		iPosY = (pMenu == tDummyDiagram.pSaveMenu) ?
134 					-1 : pEvent->data.mouse.pos.y;
135 		Menu_Show(pMenu, pEvent->data.mouse.pos.x, iPosY);
136 		return TRUE;
137 	}
138 	if (pEvent->data.mouse.window == pDiag->tMainWindow &&
139 	    pEvent->data.mouse.icon == -1) {
140 		vMainButtonClick(&pEvent->data.mouse);
141 		return TRUE;
142 	}
143 	if (pEvent->data.mouse.window == pDiag->tScaleWindow &&
144 	    pEvent->data.mouse.icon >= 0) {
145 		vScaleButtonClick(&pEvent->data.mouse, pDiag);
146 		return TRUE;
147 	}
148 	return FALSE;
149 } /* end of bMouseButtonClick */
150 
151 /*
152  * bAutoRedrawWindow - the redraw is handled by the WIMP
153  */
154 static BOOL
bAutoRedrawWindow(event_pollblock * pEvent,void * pvReference)155 bAutoRedrawWindow(event_pollblock *pEvent, void *pvReference)
156 {
157 	return TRUE;
158 } /* end of bAutoRedrawWindow */
159 
160 static BOOL
bSaveSelect(event_pollblock * pEvent,void * pvReference)161 bSaveSelect(event_pollblock *pEvent, void *pvReference)
162 {
163 	TRACE_MSG("bSaveSelect");
164 
165 	fail(pEvent == NULL);
166 	fail(pEvent->type != event_MENU);
167 	fail(pvReference == NULL);
168 
169 	DBG_DEC(pEvent->data.selection[0]);
170 
171 	switch (pEvent->data.selection[0]) {
172 	case SAVEMENU_SCALEVIEW:
173 		return bScaleOpenAction(pEvent, pvReference);
174 	case SAVEMENU_SAVEDRAW:
175 		return bSaveDrawfile(pEvent, pvReference);
176 	case SAVEMENU_SAVETEXT:
177 		return bSaveTextfile(pEvent, pvReference);
178 	default:
179 		DBG_DEC(pEvent->data.selection[0]);
180 		return FALSE;
181 	}
182 } /* end of bSaveSelect */
183 
184 /*
185  * Create the window for the text from the given file
186  */
187 static diagram_type *
pCreateTextWindow(const char * szFilename)188 pCreateTextWindow(const char *szFilename)
189 {
190 	diagram_type	*pDiag;
191 
192 	TRACE_MSG("pCreateTextWindow");
193 
194 	fail(szFilename == NULL || szFilename[0] == '\0');
195 
196 	/* Create the diagram */
197 	pDiag = pCreateDiagram(szTask+1, szFilename);
198 	if (pDiag == NULL) {
199 		werr(0, "Sorry, no new diagram object");
200 		return NULL;
201 	}
202 
203 	/* Prepare a save menu for this diagram */
204 	pDiag->pSaveMenu = Menu_New(szTask+1,
205 		">Scale view,"
206 		">Save (Drawfile)   F3,"
207 		">Save (Text only) \213F3");
208 	if (pDiag->pSaveMenu == NULL) {
209 		werr(1, "Sorry, no Savemenu object");
210 	}
211 	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SCALEVIEW,
212 					TRUE, bScaleOpenAction, pDiag);
213 	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVEDRAW,
214 					TRUE, bSaveDrawfile, pDiag);
215 	Menu_Warn(pDiag->pSaveMenu, SAVEMENU_SAVETEXT,
216 					TRUE, bSaveTextfile, pDiag);
217 
218 	/* Claim events for the main window */
219         Event_Claim(event_REDRAW, pDiag->tMainWindow, icon_ANY,
220                                         bRedrawMainWindow, pDiag);
221         Event_Claim(event_CLOSE, pDiag->tMainWindow, icon_ANY,
222                                         bDestroyDiagram, pDiag);
223         Event_Claim(event_CLICK, pDiag->tMainWindow, icon_ANY,
224                                         bMouseButtonClick, pDiag);
225         Event_Claim(event_KEY, pDiag->tMainWindow, icon_ANY,
226                                         bMainKeyPressed, pDiag);
227 
228 	/* Claim events for the scale window */
229 	Event_Claim(event_REDRAW, pDiag->tScaleWindow, icon_ANY,
230 					bAutoRedrawWindow, NULL);
231         Event_Claim(event_CLICK, pDiag->tScaleWindow, icon_ANY,
232                                         bMouseButtonClick, pDiag);
233         Event_Claim(event_KEY, pDiag->tScaleWindow, icon_ANY,
234                                         bScaleKeyPressed, pDiag);
235 
236 	/* Set the window title */
237 	vSetTitle(pDiag);
238 	return pDiag;
239 } /* end of pCreateTextWindow */
240 
241 /*
242  * vProcessFile - process one file
243  */
244 static void
vProcessFile(const char * szFilename,int iFiletype)245 vProcessFile(const char *szFilename, int iFiletype)
246 {
247 	options_type	tOptions;
248 	FILE		*pFile;
249 	diagram_type	*pDiag;
250 	long		lFilesize;
251 	int		iWordVersion;
252 
253 	TRACE_MSG("vProcessFile");
254 
255 	fail(szFilename == NULL || szFilename[0] == '\0');
256 
257 	DBG_MSG(szFilename);
258 
259 	pFile = fopen(szFilename, "rb");
260 	if (pFile == NULL) {
261 		werr(0, "I can't open '%s' for reading", szFilename);
262 		return;
263 	}
264 
265 	lFilesize = lGetFilesize(szFilename);
266 	if (lFilesize < 0) {
267 		(void)fclose(pFile);
268 		werr(0, "I can't get the size of '%s'", szFilename);
269 		return;
270 	}
271 
272 	iWordVersion = iGuessVersionNumber(pFile, lFilesize);
273 	if (iWordVersion < 0 || iWordVersion == 3) {
274 		if (bIsRtfFile(pFile)) {
275 			werr(0, "%s is not a Word Document."
276 				" It is probably a Rich Text Format file",
277 				szFilename);
278 		} if (bIsWordPerfectFile(pFile)) {
279 			werr(0, "%s is not a Word Document."
280 				" It is probably a Word Perfect file",
281 				szFilename);
282 		} else {
283 			werr(0, "%s is not a Word Document.", szFilename);
284 		}
285 		(void)fclose(pFile);
286 		return;
287 	}
288 	/* Reset any reading done during file-testing */
289 	rewind(pFile);
290 
291 	if (iFiletype != FILETYPE_MSWORD) {
292 		vGetOptions(&tOptions);
293 		if (tOptions.bAutofiletypeAllowed) {
294 			vSetFiletype(szFilename, FILETYPE_MSWORD);
295 		}
296 	}
297 
298 	pDiag = pCreateTextWindow(szFilename);
299 	if (pDiag == NULL) {
300 		(void)fclose(pFile);
301 		return;
302 	}
303 
304 	(void)bWordDecryptor(pFile, lFilesize, pDiag);
305 	Error_CheckFatal(Drawfile_VerifyDiagram(&pDiag->tInfo));
306 	vShowDiagram(pDiag);
307 	TRACE_MSG("After vShowDiagram");
308 
309 	TRACE_MSG("before debug print");
310 	DBG_HEX(pFile);
311 	TRACE_MSG("before fclose");
312 	(void)fclose(pFile);
313 	TRACE_MSG("after fclose");
314 } /* end of vProcessFile */
315 
316 /*
317  * vSendAck - send an acknowledge
318  */
319 static void
vSendAck(event_pollblock * pEvent)320 vSendAck(event_pollblock *pEvent)
321 {
322 	message_block	tMessage;
323 
324 	TRACE_MSG("vSendAck");
325 
326 	fail(pEvent == NULL);
327 	fail(pEvent->type != event_SEND && pEvent->type != event_SENDWANTACK);
328 	fail(pEvent->data.message.header.action != message_DATALOAD &&
329 		pEvent->data.message.header.action != message_DATAOPEN);
330 
331 	tMessage.header.action = message_DATALOADACK;
332 	tMessage.header.size = sizeof(tMessage);
333 	tMessage.header.yourref = pEvent->data.message.header.myref;
334 	Error_CheckFatal(Wimp_SendMessage(event_SEND, &tMessage,
335 				pEvent->data.message.header.sender, 0));
336 } /* end of vSendAck */
337 
338 static BOOL
bEventMsgHandler(event_pollblock * pEvent,void * pvReference)339 bEventMsgHandler(event_pollblock *pEvent, void *pvReference)
340 {
341 	TRACE_MSG("bEventMsgHandler");
342 
343 	fail(pEvent == NULL);
344 
345 	switch (pEvent->type) {
346 	case event_SEND:
347 	case event_SENDWANTACK:
348 		switch (pEvent->data.message.header.action) {
349 		case message_CLOSEDOWN:
350 			exit(EXIT_SUCCESS);
351 			break;
352 		case message_DATALOAD:
353 		case message_DATAOPEN:
354 			vProcessFile(
355 				pEvent->data.message.data.dataload.filename,
356 				pEvent->data.message.data.dataload.filetype);
357 			vSendAck(pEvent);
358 			break;
359 		default:
360 			DBG_DEC(pEvent->data.message.header.action);
361 			break;
362 		}
363 		return TRUE;
364 	default:
365 		DBG_DEC(pEvent->type);
366 		return FALSE;
367 	}
368 } /* end of bEventMsgHandler */
369 
370 /*
371  * bMenuSelect - select from the iconbar menu
372  */
373 static BOOL
bMenuSelect(event_pollblock * pEvent,void * pvReference)374 bMenuSelect(event_pollblock *pEvent, void *pvReference)
375 {
376 	TRACE_MSG("bMenuSelect");
377 
378 	fail(pEvent == NULL);
379 	fail(pEvent->type != event_MENU);
380 
381 	DBG_DEC(pEvent->data.selection[0]);
382 
383 	switch (pEvent->data.selection[0]) {
384 	case ICONBAR_INFO_FIELD:
385 		return bBarInfo(pEvent, pvReference);
386 	case ICONBAR_CHOICES_FIELD:
387 		vChoicesOpenAction(tChoicesWindow);
388 		Window_BringToFront(tChoicesWindow);
389 		break;
390 	case ICONBAR_QUIT_FIELD:
391 		TRACE_MSG("before exit");
392 		exit(EXIT_SUCCESS);
393 		break;
394 	default:
395 		DBG_DEC(pEvent->data.selection[0]);
396 		break;
397 	}
398 	return TRUE;
399 } /* end of bMenuSelect */
400 
401 /*
402  * bMenuClick - respond to an menu click
403  */
404 static BOOL
bMenuClick(event_pollblock * pEvent,void * pvReference)405 bMenuClick(event_pollblock *pEvent, void *pvReference)
406 {
407 	TRACE_MSG("bMenuClick");
408 
409 	fail(pEvent == NULL);
410 	fail(pEvent->type != event_MENU);
411 
412 	if (menu_currentopen == tDummyDiagram.pSaveMenu) {
413 		return bMenuSelect(pEvent, pvReference);
414 	} else if (pvReference == NULL) {
415 		return FALSE;
416 	}
417 	return bSaveSelect(pEvent, pvReference);
418 } /* end of bMenuClick */
419 
420 static void
vTemplates(void)421 vTemplates(void)
422 {
423 	TRACE_MSG("vTemplates");
424 
425 	Template_Initialise();
426 	Template_LoadFile("Templates");
427 
428 	tChoicesWindow = Window_Create("Choices", template_TITLEMIN);
429 	if (tChoicesWindow == 0) {
430 		werr(1, "I can't find the 'Choices' template");
431 	}
432 
433 	/* Claim events for the choices window */
434 	Event_Claim(event_REDRAW, tChoicesWindow, icon_ANY,
435 					bAutoRedrawWindow, NULL);
436 	Event_Claim(event_CLICK, tChoicesWindow, icon_ANY,
437 					bChoicesMouseClick, NULL);
438 	Event_Claim(event_KEY, tChoicesWindow, icon_ANY,
439 					bChoicesKeyPressed, NULL);
440 } /* end of vTemplates */
441 
442 static void
vInitialise(void)443 vInitialise(void)
444 {
445 	int	aiMessages[] = {0};
446 	icon_handle	tBarIcon;
447 
448 
449 	TRACE_MSG("vInitialise");
450 
451 	Resource_Initialise(szTask+1);
452 	Event_Initialise3(szTask+1, 310, aiMessages);
453 	EventMsg_Initialise();
454 	Screen_CacheModeInfo();
455 #if defined(__GNUC__)
456 	flex_init(szTask+1, 0, 0);
457 	flex_set_budge(1);
458 #endif /* __GNUC__ */
459 	vTemplates();
460 
461 	/* Prepare iconbar menu */
462 	tDummyDiagram.tInfo.data = NULL;
463 	tDummyDiagram.tInfo.length = 0;
464 	tDummyDiagram.pSaveMenu = Menu_New(szTask+1, ">Info,Choices...,Quit");
465 	if (tDummyDiagram.pSaveMenu == NULL) {
466 		werr(1, "Sorry, no Barmenu object");
467 	}
468 	pInfoBox = Dialog2_CreateDialogBlock("ProgInfo", -1, -1,
469 					vBarInfoSetText, NULL, NULL);
470 
471 	if (pInfoBox == NULL) {
472 		werr(1, "Sorry, no Infobox object");
473 	}
474 	Menu_Warn(tDummyDiagram.pSaveMenu, ICONBAR_INFO_FIELD,
475 					TRUE, bBarInfo, &tDummyDiagram);
476 
477 	/* Create an icon on the icon bar */
478 	tBarIcon = Icon_BarIcon(szTask, iconbar_RIGHT);
479 	Event_Claim(event_CLICK, window_ICONBAR, tBarIcon,
480 					bMouseButtonClick, &tDummyDiagram);
481 
482 	/* Generic claims */
483 	Event_Claim(event_OPEN, window_ANY, icon_ANY,
484 					Handler_OpenWindow, NULL);
485 	Event_Claim(event_CLOSE, window_ANY, icon_ANY,
486 					Handler_CloseWindow, NULL);
487 	Event_Claim(event_MENU, window_ANY, icon_ANY,
488 					bMenuClick, NULL);
489 	EventMsg_Claim(message_DATALOAD, window_ICONBAR,
490 					bEventMsgHandler, NULL);
491 	EventMsg_Claim(message_MODECHANGE, window_ANY,
492 					Handler_ModeChange, NULL);
493 } /* end of vInitialise */
494 
495 int
main(int argc,char ** argv)496 main(int argc, char **argv)
497 {
498 	int	iFirst, iFiletype;
499 
500 	TRACE_MSG("main");
501 
502 	vInitialise();
503 	iFirst = iReadOptions(argc, argv);
504 	if (iFirst != 1) {
505 		return EXIT_FAILURE;
506 	}
507 
508 	if (argc > 1) {
509 		iFiletype = iGetFiletype(argv[1]);
510 		if (iFiletype < 0) {
511 			return EXIT_FAILURE;
512 		}
513 		vProcessFile(argv[1], iFiletype);
514 		TRACE_MSG("main after vProcessFile");
515 	}
516 
517 	for (;;) {
518 		Event_Poll();
519 	}
520 } /* end of main */
521