1 /* mview.c -- File viewer
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA
26 @section mview-synopsis SYNOPSIS
28 mview [ XT-OPTION ...] [ OPTION ... ] [ FILE ]
30 @section mview-description DESCRIPTION
32 Display FILE on a window.
34 If FILE is omitted, the input is taken from standard input.
36 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
38 The following OPTIONs are available.
44 ENCODING is the encoding of FILE (defaults to UTF-8).
48 FONTSIZE is the fontsize in point. If ommited, it defaults to the
49 size of the default font defined in X resource.
65 #include <X11/Intrinsic.h>
66 #include <X11/StringDefs.h>
67 #include <X11/Shell.h>
68 #include <X11/Xaw/Form.h>
69 #include <X11/Xaw/Command.h>
70 #include <X11/Xaw/Viewport.h>
73 #include <m17n-misc.h>
78 /* Global m17n variables. */
85 /* Callback procedure for "quit". */
88 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
90 XtAppSetExitFlag (XtWidgetToApplicationContext (w));
94 /* Move POS to the next line head in M-text MT whose length is LEN.
95 If POS is already on the last line, set POS to LEN. */
97 #define NEXTLINE(pos, len) \
99 pos = mtext_character (mt, pos, len, '\n'); \
107 /* Action procedure for expose event. Redraw partial area of the
108 widget W. The area is specified in EVENT. */
111 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
113 XExposeEvent *expose = (XExposeEvent *) event;
114 int len = mtext_len (mt);
119 /* We must update the area between the Y-positions expose->y and
120 (expose->y + expose->height). We ignore X-positions. */
122 /* At first, find the line that occupies the Y-position expose->y.
123 That is the first line to draw. */
129 mdraw_text_extents (frame, mt, from, to, &control, NULL, NULL, &rect);
130 if (to == len || y + rect.height > expose->y)
134 /* The first character to draw is at position FROM. Remeber the
135 Y-position to start drawing. */
138 /* Next, find the line that occupies the Y-position (expose->y +
139 expose->height). That is the last line to draw. This time, we
140 enable caching to utilize it in the later drawing. */
142 control.disable_caching = 0;
143 while (to < len && y < expose->y + expose->height)
147 mdraw_text_extents (frame, mt, pos, to, &control, NULL, NULL, &rect);
151 /* It is decided that we must draw from FROM to the previous
153 mdraw_text_with_control (frame, (MDrawWindow) XtWindow (w),
154 0, yoff, mt, from, to, &control);
156 /* Disable caching again. */
157 control.disable_caching = 1;
159 /* If the widget was vertically enlarged too much, shrink it. */
160 if (metric.height < expose->y + expose->height)
164 XtSetArg (arg, XtNheight, metric.height);
165 XtSetValues (w, &arg, 0);
170 /* Print the usage of this program (the name is PROG), and exit with
174 help_exit (char *prog, int exit_code)
182 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] [ FILE ]\n", prog);
183 printf ("Display FILE on a window.\n");
184 printf (" If FILE is omitted, the input is taken from standard input.\n");
185 printf (" XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
186 printf ("The following OPTIONs are available.\n");
187 printf (" %-13s %s", "-e ENCODING",
188 "ENCODING is the encoding of FILE (defaults to UTF-8).\n");
189 printf (" %-13s %s", "-s FONTSIZE",
190 "FONTSIZE is the fontsize in point.\n");
191 printf ("\t\tIf ommited, it defaults to the size\n");
192 printf ("\t\tof the default font defined in X resource.\n");
193 printf (" %-13s %s", "--version", "print version number\n");
194 printf (" %-13s %s", "-h, --help", "print this message\n");
199 /* Format MSG by FMT and print the result to the stderr, and exit. */
201 #define FATAL_ERROR(fmt, arg) \
203 fprintf (stderr, fmt, arg); \
208 /* Adjust FONTSIZE for the resolution of the screen of widget W. */
211 adjust_fontsize (Widget w, int fontsize)
213 Display *display = XtDisplay (w);
214 int screen_number = XScreenNumberOfScreen (XtScreen (w));
215 double pixels = DisplayHeight (display, screen_number);
216 double mm = DisplayHeightMM (display, screen_number);
218 return (fontsize * pixels * 25.4 / mm / 100);
223 main (int argc, char **argv)
225 XtAppContext context;
226 Widget shell, form, quit, viewport, text;
227 String quit_action = "<KeyPress>q: set() notify() unset()";
228 XtActionsRec actions[] = { {"Expose", ExposeProc} };
231 int viewport_width, viewport_height;
232 char *coding_name = NULL;
237 /* Open an application context. */
238 XtSetLanguageProc (NULL, NULL, NULL);
239 shell = XtOpenApplication (&context, "MView", NULL, 0, &argc, argv, NULL,
240 sessionShellWidgetClass, NULL, 0);
241 XtAppAddActions (context, actions, XtNumber (actions));
243 /* Parse the remaining command line arguments. */
244 for (i = 1; i < argc; i++)
246 if (! strcmp (argv[i], "--help")
247 || ! strcmp (argv[i], "-h"))
248 help_exit (argv[0], 0);
249 else if (! strcmp (argv[i], "--version"))
251 printf ("mview (m17n library) %s\n", VERSION);
252 printf ("Copyright (C) 2003 AIST, JAPAN\n");
255 else if (! strcmp (argv[i], "-e"))
258 coding_name = argv[i];
260 else if (! strcmp (argv[i], "-s"))
266 FATAL_ERROR ("Invalid fontsize %s!\n", argv[i]);
267 fontsize = adjust_fontsize (shell, (int) (n * 10));
269 else if (argv[i][0] != '-')
271 fp = fopen (argv[i], "r");
273 FATAL_ERROR ("Fail to open the file %s!\n", argv[i]);
277 printf ("Unknown option: %s", argv[i]);
278 help_exit (argv[0], 1);
282 /* Initialize the m17n library. */
284 if (merror_code != MERROR_NONE)
285 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library.");
287 /* Decide how to decode the input stream. */
290 coding = mconv_resolve_coding (msymbol (coding_name));
292 FATAL_ERROR ("Invalid coding: %s\n", coding_name);
295 coding = Mcoding_utf_8;
297 mt = mconv_decode_stream (coding, fp);
300 FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!");
303 MPlist *param = mplist ();
304 MFace *face = mface ();
307 mface_put_prop (face, Msize, (void *) fontsize);
308 mplist_put (param, Mwidget, shell);
309 mplist_put (param, Mface, face);
310 frame = mframe (param);
311 m17n_object_unref (param);
312 m17n_object_unref (face);
315 /* Create this widget hierarchy.
316 Shell - form -+- quit
318 +- viewport - text */
320 form = XtCreateManagedWidget ("form", formWidgetClass, shell, NULL, 0);
321 XtSetArg (arg[0], XtNleft, XawChainLeft);
322 XtSetArg (arg[1], XtNright, XawChainLeft);
323 XtSetArg (arg[2], XtNtop, XawChainTop);
324 XtSetArg (arg[3], XtNbottom, XawChainTop);
325 XtSetArg (arg[4], XtNaccelerators, XtParseAcceleratorTable (quit_action));
326 quit = XtCreateManagedWidget ("quit", commandWidgetClass, form, arg, 5);
327 XtAddCallback (quit, XtNcallback, QuitProc, NULL);
329 viewport_width = (int) mframe_get_prop (frame, Mfont_width) * 80;
331 = ((int) mframe_get_prop (frame, Mfont_ascent)
332 + (int) mframe_get_prop (frame, Mfont_descent)) * 24;
333 XtSetArg (arg[0], XtNallowVert, True);
334 XtSetArg (arg[1], XtNforceBars, False);
335 XtSetArg (arg[2], XtNfromVert, quit);
336 XtSetArg (arg[3], XtNtop, XawChainTop);
337 XtSetArg (arg[4], XtNbottom, XawChainBottom);
338 XtSetArg (arg[5], XtNright, XawChainRight);
339 XtSetArg (arg[6], XtNwidth, viewport_width);
340 XtSetArg (arg[7], XtNheight, viewport_height);
341 viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, form,
344 /* Before creating the text widget, we must calculate the height of
345 the M-text to draw. */
346 control.two_dimensional = 1;
347 control.enable_bidi = 1;
348 control.disable_caching = 1;
349 control.max_line_width = viewport_width;
350 mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control,
351 NULL, NULL, &metric);
354 /* Decide the size of the text widget. */
355 XtSetArg (arg[0], XtNwidth, viewport_width);
356 if (viewport_height > metric.height)
357 /* The outer viewport is tall enough. */
358 XtSetArg (arg[1], XtNheight, viewport_height);
359 else if (metric.height < 0x8000)
360 /* The M-text height is within the limit of X. */
361 XtSetArg (arg[1], XtNheight, metric.height);
363 /* We can't make such a tall widget. Truncate it. */
364 XtSetArg (arg[1], XtNheight, 0x7FFF);
366 /* We must provide our own expose event handler. */
367 XtSetArg (arg[2], XtNtranslations,
368 XtParseTranslationTable ((String) "<Expose>: Expose()"));
369 text = XtCreateManagedWidget ("text", simpleWidgetClass, viewport, arg, 3);
372 /* Realize the top widget, and dive into an even loop. */
373 XtInstallAllAccelerators (form, form);
374 XtRealizeWidget (shell);
375 XtAppMainLoop (context);
378 m17n_object_unref (mt);
379 m17n_object_unref (frame);
384 #endif /* not FOR_DOXYGEN */