1 /* mview.c -- File viewer -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
5
6 This file is part of the m17n library.
7
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
12
13 The m17n library 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 GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301 USA. */
22
23 /***en
24 @enpage m17n-view view file
25
26 @section m17n-view-synopsis SYNOPSIS
27
28 m17n-view [ XT-OPTION ...] [ OPTION ... ] [ FILE ]
29
30 @section m17n-view-description DESCRIPTION
31
32 Display FILE on a window.
33
34 If FILE is omitted, the input is taken from standard input.
35
36 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
37
38 The following OPTIONs are available.
39
40 <ul>
41
42 <li> -e ENCODING
43
44 ENCODING is the encoding of FILE (defaults to UTF-8).
45
46 <li> -s FONTSIZE
47
48 FONTSIZE is the fontsize in point. If omitted, it defaults to the
49 size of the default font defined in X resource.
50
51 <li> --version
52
53 Print version number.
54
55 <li> -h, --help
56
57 Print this message.
58
59 </ul>
60 */
61 /***ja
62 @japage m17n-view �ե������
63
64 @section m17n-view-synopsis SYNOPSIS
65
66 m17n-view [ XT-OPTION ...] [ OPTION ... ] [ FILE ]
67
68 @section m17n-view-description DESCRIPTION
69
70 FILE ����ɥ���ɽ�����롣
71
72 FILE ����ά���줿���ϡ�ɸ�����Ϥ���Ȥ롣
73
74 XT-OPTIONs �� Xt ��ɸ��ΰ����Ǥ��롣 (e.g. -fn, -fg).
75
76 �ʲ��Υ��ץ�������ѤǤ��롣
77
78 <ul>
79
80 <li> -e ENCODING
81
82 ENCODING �� FILE �Υ����ɷϤǤ��롣(�ǥե���Ȥ� UTF-8)
83
84 <li> -s FONTSIZE
85
86 FONTSIZE �ϥե���Ȥ��礭����ݥ����ñ�̤Ǽ�������ΤǤ��롣��ά
87 ���줿���ϡ�X �Υ������������줿�ǥե���ȥե���Ȥ��礭����
88 �ʤ롣
89
90 <li> --version
91
92 �С�������ֹ��ɽ�����롣
93
94 <li> -h, --help
95
96 ���Υ�å�������ɽ�����롣
97
98 </ul>
99 */
100 #ifndef FOR_DOXYGEN
101
102 #include <stdio.h>
103 #include <stdlib.h>
104
105 #ifdef HAVE_X11_XAW_COMMAND_H
106
107 #include <X11/Intrinsic.h>
108 #include <X11/StringDefs.h>
109 #include <X11/Shell.h>
110
111 #include <m17n-gui.h>
112 #include <m17n-misc.h>
113 #include <m17n-X.h>
114
115 #include <X11/Xaw/Form.h>
116 #include <X11/Xaw/Command.h>
117 #include <X11/Xaw/Viewport.h>
118
119 /* Global m17n variables. */
120 MFrame *frame;
121 MText *mt;
122 MDrawMetric metric;
123 MDrawControl control;
124
125
126 /* Callback procedure for "quit". */
127
128 void
QuitProc(Widget w,XtPointer client_data,XtPointer call_data)129 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
130 {
131 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
132 }
133
134
135 /* Move POS to the next line head in M-text MT whose length is LEN.
136 If POS is already on the last line, set POS to LEN. */
137
138 #define NEXTLINE(pos, len) \
139 do { \
140 pos = mtext_character (mt, pos, len, '\n'); \
141 if (pos < 0) \
142 pos = len; \
143 else \
144 pos++; \
145 } while (0)
146
147
148 /* Action procedure for expose event. Redraw partial area of the
149 widget W. The area is specified in EVENT. */
150
151 static void
ExposeProc(Widget w,XEvent * event,String * str,Cardinal * num)152 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
153 {
154 XExposeEvent *expose = (XExposeEvent *) event;
155 int len = mtext_len (mt);
156 int pos, from, to;
157 int y = 0, yoff = 0;
158 MDrawMetric rect;
159
160 /* We must update the area between the Y-positions expose->y and
161 (expose->y + expose->height). We ignore X-positions. */
162
163 /* At first, find the line that occupies the Y-position expose->y.
164 That is the first line to draw. */
165 to = 0;
166 while (1)
167 {
168 from = to;
169 NEXTLINE (to, len);
170 mdraw_text_extents (frame, mt, from, to, &control, NULL, NULL, &rect);
171 if (to == len || y + rect.height > expose->y)
172 break;
173 y += rect.height;
174 }
175 /* The first character to draw is at position FROM. Remeber the
176 Y-position to start drawing. */
177 yoff = y - rect.y;
178
179 /* Next, find the line that occupies the Y-position (expose->y +
180 expose->height). That is the last line to draw. This time, we
181 enable caching to utilize it in the later drawing. */
182 y += rect.height;
183 control.disable_caching = 0;
184 while (to < len && y < expose->y + expose->height)
185 {
186 pos = to;
187 NEXTLINE (to, len);
188 mdraw_text_extents (frame, mt, pos, to, &control, NULL, NULL, &rect);
189 y += rect.height;
190 }
191
192 /* It is decided that we must draw from FROM to the previous
193 character of TO. */
194 mdraw_text_with_control (frame, (MDrawWindow) XtWindow (w),
195 0, yoff, mt, from, to, &control);
196
197 /* Disable caching again. */
198 control.disable_caching = 1;
199
200 /* If the widget was vertically enlarged too much, shrink it. */
201 if (metric.height < expose->y + expose->height)
202 {
203 Arg arg;
204
205 XtSetArg (arg, XtNheight, metric.height);
206 XtSetValues (w, &arg, 0);
207 }
208 }
209
210
211 /* Print the usage of this program (the name is PROG), and exit with
212 EXIT_CODE. */
213
214 void
help_exit(char * prog,int exit_code)215 help_exit (char *prog, int exit_code)
216 {
217 char *p = prog;
218
219 while (*p)
220 if (*p++ == '/')
221 prog = p;
222
223 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] [ FILE ]\n", prog);
224 printf ("Display FILE on a window.\n");
225 printf (" If FILE is omitted, the input is taken from standard input.\n");
226 printf (" XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
227 printf ("The following OPTIONs are available.\n");
228 printf (" %-13s %s", "-e ENCODING",
229 "ENCODING is the encoding of FILE (defaults to UTF-8).\n");
230 printf (" %-13s %s", "-s FONTSIZE",
231 "FONTSIZE is the fontsize in point.\n");
232 printf ("\t\tIf omitted, it defaults to the size\n");
233 printf ("\t\tof the default font defined in X resource.\n");
234 printf (" %-13s %s", "--version", "print version number\n");
235 printf (" %-13s %s", "-h, --help", "print this message\n");
236 exit (exit_code);
237 }
238
239
240 /* Format MSG by FMT and print the result to the stderr, and exit. */
241
242 #define FATAL_ERROR(fmt, arg) \
243 do { \
244 fprintf (stderr, fmt, arg); \
245 exit (1); \
246 } while (0)
247
248
249 /* Adjust FONTSIZE for the resolution of the screen of widget W. */
250
251 int
adjust_fontsize(Widget w,int fontsize)252 adjust_fontsize (Widget w, int fontsize)
253 {
254 Display *display = XtDisplay (w);
255 int screen_number = XScreenNumberOfScreen (XtScreen (w));
256 double pixels = DisplayHeight (display, screen_number);
257 double mm = DisplayHeightMM (display, screen_number);
258
259 return (fontsize * pixels * 25.4 / mm / 100);
260 }
261
262
263 int
main(int argc,char ** argv)264 main (int argc, char **argv)
265 {
266 XtAppContext context;
267 Widget shell, form, quit, viewport, text;
268 String quit_action = "<KeyPress>q: set() notify() unset()";
269 XtActionsRec actions[] = { {"Expose", ExposeProc} };
270 Arg arg[10];
271 int i;
272 int viewport_width, viewport_height;
273 char *coding_name = NULL;
274 FILE *fp = stdin;
275 MSymbol coding;
276 int fontsize = 0;
277
278 /* Open an application context. */
279 XtSetLanguageProc (NULL, NULL, NULL);
280 shell = XtOpenApplication (&context, "M17NView", NULL, 0, &argc, argv, NULL,
281 sessionShellWidgetClass, NULL, 0);
282 XtAppAddActions (context, actions, XtNumber (actions));
283
284 /* Parse the remaining command line arguments. */
285 for (i = 1; i < argc; i++)
286 {
287 if (! strcmp (argv[i], "--help")
288 || ! strcmp (argv[i], "-h"))
289 help_exit (argv[0], 0);
290 else if (! strcmp (argv[i], "--version"))
291 {
292 printf ("m17n-view (m17n library) %s\n", M17NLIB_VERSION_NAME);
293 printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n");
294 exit (0);
295 }
296 else if (! strcmp (argv[i], "-e"))
297 {
298 i++;
299 coding_name = argv[i];
300 }
301 else if (! strcmp (argv[i], "-s"))
302 {
303 double n;
304 i++;
305 n = atof (argv[i]);
306 if (n <= 0)
307 FATAL_ERROR ("Invalid fontsize %s!\n", argv[i]);
308 fontsize = adjust_fontsize (shell, (int) (n * 10));
309 }
310 else if (argv[i][0] != '-')
311 {
312 fp = fopen (argv[i], "r");
313 if (! fp)
314 FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
315 }
316 else
317 {
318 printf ("Unknown option: %s", argv[i]);
319 help_exit (argv[0], 1);
320 }
321 }
322
323 /* Initialize the m17n library. */
324 M17N_INIT ();
325 if (merror_code != MERROR_NONE)
326 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
327
328 /* Decide how to decode the input stream. */
329 if (coding_name)
330 {
331 coding = mconv_resolve_coding (msymbol (coding_name));
332 if (coding == Mnil)
333 FATAL_ERROR ("Invalid coding: %s\n", coding_name);
334 }
335 else
336 coding = Mcoding_utf_8;
337
338 mt = mconv_decode_stream (coding, fp);
339 fclose (fp);
340 if (! mt)
341 FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
342
343 {
344 MPlist *param = mplist ();
345 MFace *face = mface ();
346
347 if (fontsize)
348 mface_put_prop (face, Msize, (void *) fontsize);
349 mplist_put (param, Mwidget, shell);
350 mplist_put (param, Mface, face);
351 frame = mframe (param);
352 m17n_object_unref (param);
353 m17n_object_unref (face);
354 }
355
356 /* Create this widget hierarchy.
357 Shell - form -+- quit
358 |
359 +- viewport - text */
360
361 form = XtCreateManagedWidget ("form", formWidgetClass, shell, NULL, 0);
362 XtSetArg (arg[0], XtNleft, XawChainLeft);
363 XtSetArg (arg[1], XtNright, XawChainLeft);
364 XtSetArg (arg[2], XtNtop, XawChainTop);
365 XtSetArg (arg[3], XtNbottom, XawChainTop);
366 XtSetArg (arg[4], XtNaccelerators, XtParseAcceleratorTable (quit_action));
367 quit = XtCreateManagedWidget ("quit", commandWidgetClass, form, arg, 5);
368 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
369
370 viewport_width = (int) mframe_get_prop (frame, Mfont_width) * 80;
371 viewport_height
372 = ((int) mframe_get_prop (frame, Mfont_ascent)
373 + (int) mframe_get_prop (frame, Mfont_descent)) * 24;
374 XtSetArg (arg[0], XtNallowVert, True);
375 XtSetArg (arg[1], XtNforceBars, False);
376 XtSetArg (arg[2], XtNfromVert, quit);
377 XtSetArg (arg[3], XtNtop, XawChainTop);
378 XtSetArg (arg[4], XtNbottom, XawChainBottom);
379 XtSetArg (arg[5], XtNright, XawChainRight);
380 XtSetArg (arg[6], XtNwidth, viewport_width);
381 XtSetArg (arg[7], XtNheight, viewport_height);
382 viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, form,
383 arg, 8);
384
385 /* Before creating the text widget, we must calculate the height of
386 the M-text to draw. */
387 control.two_dimensional = 1;
388 control.enable_bidi = 1;
389 control.disable_caching = 1;
390 control.max_line_width = viewport_width;
391 mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control,
392 NULL, NULL, &metric);
393
394 {
395 /* Decide the size of the text widget. */
396 XtSetArg (arg[0], XtNwidth, viewport_width);
397 if (viewport_height > metric.height)
398 /* The outer viewport is tall enough. */
399 XtSetArg (arg[1], XtNheight, viewport_height);
400 else if (metric.height < 0x8000)
401 /* The M-text height is within the limit of X. */
402 XtSetArg (arg[1], XtNheight, metric.height);
403 else
404 /* We can't make such a tall widget. Truncate it. */
405 XtSetArg (arg[1], XtNheight, 0x7FFF);
406
407 /* We must provide our own expose event handler. */
408 XtSetArg (arg[2], XtNtranslations,
409 XtParseTranslationTable ((String) "<Expose>: Expose()"));
410 text = XtCreateManagedWidget ("text", simpleWidgetClass, viewport, arg, 3);
411 }
412
413 /* Realize the top widget, and dive into an even loop. */
414 XtInstallAllAccelerators (form, form);
415 XtRealizeWidget (shell);
416 XtAppMainLoop (context);
417
418 /* Clear away. */
419 m17n_object_unref (mt);
420 m17n_object_unref (frame);
421 M17N_FINI ();
422
423 exit (0);
424 }
425
426 #else /* not HAVE_X11_XAW_COMMAND_H */
427
428 int
main(int argc,char ** argv)429 main (int argc, char **argv)
430 {
431 fprintf (stderr,
432 "Building of this program failed (lack of some header files)\n");
433 exit (1);
434 }
435
436 #endif /* not HAVE_X11_XAW_COMMAND_H */
437
438 #endif /* not FOR_DOXYGEN */
439