1 /* $XConsortium: xmapdef.c /main/4 1995/07/15 20:47:41 drk $ */
2 /*
3 * Motif
4 *
5 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6 *
7 * These libraries and programs are free software; you can
8 * redistribute them and/or modify them under the terms of the GNU
9 * Lesser General Public License as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * These libraries and programs are distributed in the hope that
14 * they will be useful, but WITHOUT ANY WARRANTY; without even the
15 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU Lesser General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with these librararies and programs; if not, write
21 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22 * Floor, Boston, MA 02110-1301 USA
23 */
24 /*
25 * HISTORY
26 */
27 /*
28 ** This demo shows an APPLICATION_DEFINED scrolled window.
29 **
30 ** It's a file viewer that uses a FSB for filename input and
31 ** a viewport with a vertical scrollbar to see the file.
32 ** The file is shown using the per screen font resource.
33 **
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <Xm/XmAll.h>
39
40 /*-------------------------------------------------------------
41 ** Forwarded functions
42 */
43 void CreateApplication ();
44 void WarnUser ();
45 Widget CreateHelp ();
46
47 /* Xt callbacks
48 */
49 void DrawCB ();
50 void ValueCB ();
51 void OpenCB ();
52 void ReadCB ();
53 void QuitCB ();
54 void HelpCB ();
55
56 /*-------------------------------------------------------------
57 ** File i/o and drawing stuff
58 */
59 void InitFile ();
60 Boolean BuildLineTable ();
61 void ReDraw ();
62 void ReSize ();
63
64 typedef struct {
65 Widget work_area ;
66 Widget v_scrb ;
67 String file_name ;
68 XFontStruct * font_struct ;
69 GC draw_gc ;
70 char ** lines ;
71 int num_lines ;
72 } FileData ;
73
74
75 /*-------------------------------------------------------------
76 ** Main body
77 */
main(argc,argv)78 int main(argc, argv)
79 int argc; char **argv;
80 {
81 XtAppContext app_context;
82 Widget toplevel ;
83 FileData filedata ;
84
85 toplevel = XtAppInitialize(&app_context, "XMdemos", NULL, 0,
86 &argc, argv, NULL, NULL, 0);
87
88 InitFile(toplevel, &filedata, argc, argv);
89
90 CreateApplication (toplevel, &filedata);
91
92 XtRealizeWidget(toplevel);
93 XtAppMainLoop(app_context);
94
95 return 0; /* make compiler happy */
96 }
97
98
99 /*-------------------------------------------------------------
100 ** Create a app_defined Main Window with a Menubar to load a file
101 ** Add the vertical scrollbar and the workarea to filedata.
102 */
CreateApplication(parent,filedata)103 void CreateApplication (parent, filedata)
104 Widget parent;
105 FileData * filedata;
106 {
107 Widget main_window, menu_bar, menu_pane, cascade,
108 button ;
109 Arg args[5];
110 int n ;
111
112
113 /* Create app_defined MainWindow.
114 */
115 n = 0;
116 XtSetArg (args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED); n++;
117 main_window = XmCreateMainWindow (parent, "main_window", args, n);
118 XtManageChild (main_window);
119
120
121 /* Create MenuBar in MainWindow.
122 */
123 n = 0;
124 menu_bar = XmCreateMenuBar (main_window, "menu_bar", args, n);
125 XtManageChild (menu_bar);
126
127
128 /* Create "File" PulldownMenu with Load and Quit buttons
129 */
130 n = 0;
131 menu_pane = XmCreatePulldownMenu (menu_bar, "menu_pane", args, n);
132
133 n = 0;
134 button = XmCreatePushButton (menu_pane, "Open...", args, n);
135 XtManageChild (button);
136 /* pass the graphic id to the save function */
137 XtAddCallback (button, XmNactivateCallback, OpenCB, (XtPointer)filedata);
138 n = 0;
139 button = XmCreatePushButton (menu_pane, "Quit", args, n);
140 XtManageChild (button);
141 XtAddCallback (button, XmNactivateCallback, QuitCB, NULL);
142
143 n = 0;
144 XtSetArg (args[n], XmNsubMenuId, menu_pane); n++;
145 cascade = XmCreateCascadeButton (menu_bar, "File", args, n);
146 XtManageChild (cascade);
147
148
149 /* Create "Help" PulldownMenu with Help button.
150 */
151 n = 0;
152 menu_pane = XmCreatePulldownMenu (menu_bar, "menu_pane", args, n);
153
154 n = 0;
155 button = XmCreatePushButton (menu_pane, "Help", args, n);
156 XtManageChild (button);
157 XtAddCallback (button, XmNactivateCallback, HelpCB, NULL);
158
159 n = 0;
160 XtSetArg (args[n], XmNsubMenuId, menu_pane); n++;
161 cascade = XmCreateCascadeButton (menu_bar, "Help", args, n);
162 XtManageChild (cascade);
163
164 n = 0;
165 XtSetArg (args[n], XmNmenuHelpWidget, cascade); n++;
166 XtSetValues (menu_bar, args, n);
167
168
169 /* Create vertical scrollbar only
170 */
171 n = 0;
172 XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
173 filedata->v_scrb = XmCreateScrollBar (main_window, "v_scrb", args, n);
174 XtAddCallback (filedata->v_scrb, XmNvalueChangedCallback, ValueCB,
175 (XtPointer)filedata);
176 XtManageChild (filedata->v_scrb);
177
178
179 /* Create work_area in MainWindow
180 */
181 n = 0;
182 filedata->work_area = XmCreateDrawingArea(main_window, "work_area", args, n);
183 XtAddCallback (filedata->work_area, XmNexposeCallback, DrawCB,
184 (XtPointer)filedata);
185 XtAddCallback (filedata->work_area, XmNresizeCallback, DrawCB,
186 (XtPointer)filedata);
187 XtManageChild (filedata->work_area);
188
189
190 /* Set MainWindow areas
191 */
192 XmMainWindowSetAreas (main_window, menu_bar, NULL, NULL,
193 filedata->v_scrb,
194 filedata->work_area);
195
196 }
197
198 /*-------------------------------------------------------------
199 ** OpenCB - callback for Open button
200 */
OpenCB(w,client_data,call_data)201 void OpenCB (w, client_data, call_data)
202 Widget w; /* widget id */
203 caddr_t client_data; /* data from application */
204 caddr_t call_data; /* data from widget class */
205 {
206 static Widget fsb_box = NULL ;
207
208 if (!fsb_box) {
209 fsb_box = XmCreateFileSelectionDialog (w, "Load file",
210 NULL, 0);
211 /* just propagate the graphic information */
212 XtAddCallback (fsb_box, XmNokCallback, ReadCB, client_data);
213 }
214
215 XtManageChild (fsb_box);
216 }
217
218
219 /*-------------------------------------------------------------
220 ** QuitCB - callback for quit button
221 */
QuitCB(w,client_data,call_data)222 void QuitCB (w, client_data, call_data)
223 Widget w; /* widget id */
224 caddr_t client_data; /* data from applicaiton */
225 caddr_t call_data; /* data from widget class */
226 {
227 exit (0);
228 }
229
230
231 /*-------------------------------------------------------------
232 ** HelpCB - callback for help button
233 */
HelpCB(w,client_data,call_data)234 void HelpCB (w, client_data, call_data)
235 Widget w; /* widget id */
236 caddr_t client_data; /* data from application */
237 caddr_t call_data; /* data from widget class */
238 {
239 static Widget message_box = NULL ;
240
241 if (!message_box) message_box = CreateHelp (w);
242
243 XtManageChild (message_box);
244 }
245
246
247
248 /*-------------------------------------------------------------
249 ** ReadCB - callback for fsb activate
250 */
ReadCB(w,client_data,call_data)251 void ReadCB (w, client_data, call_data)
252 Widget w; /* widget id */
253 caddr_t client_data; /* data from application */
254 caddr_t call_data; /* data from widget class */
255 {
256 FileData * filedata = (FileData *) client_data ;
257 String file_name ;
258 Arg args[5];
259 int n, slider_size ;
260 Dimension height ;
261
262 file_name = XmTextGetString(
263 XmFileSelectionBoxGetChild(w, XmDIALOG_TEXT)) ;
264
265 if (!BuildLineTable(filedata, file_name)) {
266 WarnUser (w, "Cannot open %s\n", file_name);
267 } else {
268 filedata->file_name = file_name ;
269
270 /* ok, we have a new file, so reset some values */
271 n = 0;
272 XtSetArg (args[n], XmNheight, &height); n++;
273 XtGetValues (filedata->work_area, args, n);
274
275 slider_size = (height - 4) / (filedata->font_struct->ascent
276 + filedata->font_struct->descent) ;
277 if (slider_size <= 0) slider_size = 1 ;
278 if (slider_size > filedata->num_lines)
279 slider_size = filedata->num_lines ;
280
281 n = 0 ;
282 XtSetArg (args[n], XmNsliderSize, slider_size); n++;
283 XtSetArg (args[n], XmNmaximum, filedata->num_lines); n++;
284 XtSetArg (args[n], XmNvalue, 0); n++;
285 XtSetValues (filedata->v_scrb, args, n);
286
287 /* clear and redraw */
288 XClearWindow(XtDisplay(filedata->work_area),
289 XtWindow(filedata->work_area));
290 ReDraw (filedata);
291 }
292 }
293
294 /*-------------------------------------------------------------
295 ** ValueCB - callback for scrollbar
296 */
ValueCB(w,client_data,call_data)297 void ValueCB (w, client_data, call_data)
298 Widget w; /* widget id */
299 caddr_t client_data; /* data from application */
300 caddr_t call_data; /* data from widget class */
301 {
302 FileData * filedata = (FileData *) client_data ;
303
304 /* clear and redraw, dumb dumb.. */
305 XClearWindow(XtDisplay(filedata->work_area),
306 XtWindow(filedata->work_area));
307 ReDraw(filedata);
308 }
309
310
311
312 /*-------------------------------------------------------------
313 ** DrawCB - callback for drawing area
314 */
DrawCB(w,client_data,call_data)315 void DrawCB (w, client_data, call_data)
316 Widget w; /* widget id */
317 caddr_t client_data; /* data from application */
318 caddr_t call_data; /* data from widget class */
319 {
320
321 XmDrawingAreaCallbackStruct * dacs =
322 (XmDrawingAreaCallbackStruct *) call_data ;
323 FileData * filedata = (FileData *) client_data ;
324 XSetWindowAttributes xswa;
325
326 static Boolean first_time = True ;
327
328 switch (dacs->reason) {
329 case XmCR_EXPOSE:
330 if (first_time) {
331 /* Change once the bit gravity of the Drawing Area; default
332 is north west and we want forget, so that resize
333 always generates exposure events */
334 first_time = False ;
335 xswa.bit_gravity = ForgetGravity ;
336 XChangeWindowAttributes(XtDisplay(w), XtWindow(w),
337 CWBitGravity, &xswa);
338 }
339
340 ReDraw(filedata) ;
341
342 break ;
343 case XmCR_RESIZE:
344 ReSize(filedata) ;
345
346 break ;
347 }
348 }
349
350 /*-------------------------------------------------------------
351 ** CreateHelp - create help window
352 */
CreateHelp(parent)353 Widget CreateHelp (parent)
354 Widget parent; /* parent widget */
355 {
356 Widget button;
357 Widget message_box; /* Message Dialog */
358 Arg args[20]; /* arg list */
359 register int n; /* arg count */
360
361 static char message[1000]; /* help text */
362 XmString title_string = NULL;
363 XmString message_string = NULL;
364 XmString button_string = NULL;
365
366 /* Generate message to display.
367 */
368 sprintf (message, "\
369 Use the Open button in the File menu to load a new file.\n\n\
370 Use the ScrollBar to scroll and the window manager to resize the main\n\
371 window and see the slider size change.\n\n\
372 You can specify which font to display the test using the\n\
373 XmNfont screen resource.");
374
375 message_string = XmStringCreateLtoR (message,
376 XmSTRING_DEFAULT_CHARSET);
377 button_string = XmStringCreateLtoR ("Close",
378 XmSTRING_DEFAULT_CHARSET);
379 title_string = XmStringCreateLtoR ("General Help",
380 XmSTRING_DEFAULT_CHARSET);
381
382
383 /* Create MessageBox dialog.
384 */
385 n = 0;
386 XtSetArg (args[n], XmNdialogTitle, title_string); n++;
387 XtSetArg (args[n], XmNokLabelString, button_string); n++;
388 XtSetArg (args[n], XmNmessageString, message_string); n++;
389 message_box = XmCreateMessageDialog (parent, "helpbox", args, n);
390
391 button = XmMessageBoxGetChild (message_box, XmDIALOG_CANCEL_BUTTON);
392 XtUnmanageChild (button);
393 button = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
394 XtUnmanageChild (button);
395
396
397 /* Free strings and return MessageBox.
398 */
399 if (title_string) XmStringFree (title_string);
400 if (message_string) XmStringFree (message_string);
401 if (button_string) XmStringFree (button_string);
402
403 return (message_box);
404 }
405
WarnUser(widget,format,name)406 void WarnUser (widget, format, name)
407 Widget widget ;
408 String format ;
409 String name ;
410 {
411 /* better ui needed */
412 printf(format, name);
413 }
414
415
416 /*************************** FILE STUFF **********************************/
417
InitFile(widget,filedata,argc,argv)418 void InitFile(widget, filedata, argc, argv)
419 Widget widget;
420 FileData * filedata;
421 int argc; char **argv;
422 {
423 Arg args[5];
424 int n ;
425 XGCValues val ;
426
427 filedata->lines = NULL ;
428 filedata->num_lines = 0 ;
429
430 /* get the X font from the screen object and make a gc */
431 n = 0;
432
433 /* do not use the screen object routine in 1.1 or lesser */
434 #if XmREVISION < 2
435 filedata->font_struct = XLoadQueryFont(XtDisplay(widget), "fixed");
436 #else
437 XtSetArg (args[n], XmNfont, &(filedata->font_struct)); n++;
438 XtGetValues (XmGetXmScreen(XDefaultScreenOfDisplay(XtDisplay(widget))),
439 args, n);
440 #endif
441 val.font = filedata->font_struct->fid ;
442 filedata->draw_gc = XtGetGC(widget, GCFont, &val);
443
444 if (argc == 2) {
445 if (BuildLineTable(filedata, argv[1])) {
446 filedata->file_name = argv[1] ;
447 } else {
448 filedata->file_name = "" ;
449 WarnUser(widget, "Cannot open %s\n", argv[1]);
450 }
451 } else {
452 filedata->file_name = "" ;
453 }
454 }
455
456
BuildLineTable(filedata,file_name)457 Boolean BuildLineTable(filedata, file_name)
458 FileData * filedata ;
459 String file_name ;
460 {
461 FILE *in_file ;
462 char linebuff[256] ;
463
464 if ((in_file = fopen(file_name, "r")) == NULL) {
465 return False ;
466 } else {
467 /* free the current data */
468 if (filedata->num_lines) {
469 while (filedata->num_lines-- >= 0) {
470 XtFree(filedata->lines[filedata->num_lines]) ;
471 }
472 XtFree ((char*)filedata->lines) ;
473 filedata->lines = NULL ;
474 filedata->num_lines = 0 ;
475 }
476 /* allocate and fill new data */
477 while (fgets (linebuff, 256, in_file)) {
478 filedata->num_lines ++ ;
479 /* better fragmentation needed... */
480 filedata->lines = (char**) XtRealloc((char*)filedata->lines,
481 filedata->num_lines * sizeof(char*)) ;
482 filedata->lines[filedata->num_lines-1] = XtNewString(linebuff);
483 }
484 return True ;
485 }
486 }
487
ReDraw(filedata)488 void ReDraw(filedata)
489 FileData * filedata ;
490 {
491 /* Display as many line as slider_size actually shows, since
492 slider_size is computed relative to the work_area height */
493
494 Cardinal i ;
495 int value, slider_size ;
496 Arg args[5];
497 int n ;
498 Position y ;
499
500 if (filedata->num_lines == 0) return ;
501
502 n = 0;
503 XtSetArg (args[n], XmNvalue, &value); n++;
504 XtSetArg (args[n], XmNsliderSize, &slider_size); n++;
505 XtGetValues (filedata->v_scrb, args, n);
506
507 for (i = value, y = 2 + filedata->font_struct->ascent;
508 i < value + slider_size ;
509 i++, y += (filedata->font_struct->ascent
510 + filedata->font_struct->descent)) {
511 XDrawString(XtDisplay(filedata->work_area),
512 XtWindow(filedata->work_area),
513 filedata->draw_gc,
514 4, y,
515 filedata->lines[i], strlen(filedata->lines[i]));
516 }
517 }
518
ReSize(filedata)519 void ReSize(filedata)
520 FileData * filedata ;
521 {
522 /* Just update the scrollbar internals here, don't bother to redisplay
523 since the gravity is none */
524
525 Arg args[5];
526 int n ;
527 int value, slider_size ;
528 Dimension height ;
529
530 if (filedata->num_lines == 0) return ;
531
532 n = 0;
533 XtSetArg (args[n], XmNheight, &height); n++;
534 XtGetValues (filedata->work_area, args, n);
535
536 /* sliderSize is the number of visible lines */
537 slider_size = (height - 4) / (filedata->font_struct->ascent
538 + filedata->font_struct->descent) ;
539 if (slider_size <= 0) slider_size = 1 ;
540 if (slider_size > filedata->num_lines)
541 slider_size = filedata->num_lines ;
542
543 n = 0;
544 XtSetArg (args[n], XmNvalue, &value); n++;
545 XtGetValues (filedata->v_scrb, args, n);
546
547 /* value shouldn't change that often but there are cases
548 where it matters */
549 if (value > filedata->num_lines - slider_size)
550 value = filedata->num_lines - slider_size;
551
552 n = 0;
553 XtSetArg (args[n], XmNsliderSize, slider_size); n++;
554 XtSetArg (args[n], XmNvalue, value); n++;
555 XtSetArg (args[n], XmNmaximum, filedata->num_lines); n++;
556 XtSetValues (filedata->v_scrb, args, n);
557 }
558
559