1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           xitMsgWin
4 --
5 --  Project:          xit   - X Internal Toolkit
6 --  System:           <>
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    Window for general messages. The messages displayed are numbered and
12 --    they can be viewed and a file log can be created.
13 --
14 --  Filename:         xitMsgWin.c
15 --
16 --  Authors:          Roger Larsson, Ulrika Bornetun
17 --  Creation date:    1992-06-16
18 --
19 --
20 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
21 --      All rights reserved
22 --
23 --  Permission to use, copy, modify, and distribute this software and its
24 --  documentation for any purpose and without fee is hereby granted,
25 --  provided that the above copyright notice appear in all copies. Ulrika
26 --  Bornetun and Roger Larsson make no representations about the usability
27 --  of this software for any purpose. It is provided "as is" without express
28 --  or implied warranty.
29 ----------------------------------------------------------------------------*/
30 
31 /* SCCS module identifier. */
32 static char SCCSID[] = "@(#) Module: xitMsgWin.c, Version: 1.1, Date: 95/02/18 15:10:42";
33 
34 
35 /*----------------------------------------------------------------------------
36 --  Include files
37 ----------------------------------------------------------------------------*/
38 
39 #include <string.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 
43 #include <X11/Intrinsic.h>
44 #include <X11/Shell.h>
45 
46 #include <Xm/Protocols.h>
47 
48 #include <Xm/Xm.h>
49 #include <Xm/RowColumn.h>
50 #include <Xm/Text.h>
51 
52 #include "System.h"
53 #include "TimDate.h"
54 
55 #include "xitTools.h"
56 #include "xitMsgWin.h"
57 
58 
59 /*----------------------------------------------------------------------------
60 --  Macro definitions
61 ----------------------------------------------------------------------------*/
62 
63 /* Local widgets in the show window. */
64 #define msgWinLa         dataLocalW[  0 ]
65 #define msgWinRc         dataLocalW[  1 ]
66 #define msgWinTx         dataLocalW[  2 ]
67 
68 
69 /*----------------------------------------------------------------------------
70 --  Type declarations
71 ----------------------------------------------------------------------------*/
72 
73 /* Record for internal data. */
74 typedef struct {
75 
76   /* Max messages to display in the message window. */
77   int  max_msg;
78 
79   /* Number of messages in the window. */
80   int  no_msg;
81 
82   /* Selected message. */
83   int  selected_msg;
84 
85   /* File name for error log file. */
86   char  *log_file;
87 
88   /* Parent window. */
89   Widget  parentW;
90 
91   /* Message window. */
92   Widget  msgWinW;
93 
94 } MSG_REC, *MSG_REC_REF;
95 
96 
97 /*----------------------------------------------------------------------------
98 --  Global definitions
99 ----------------------------------------------------------------------------*/
100 
101 
102 /*----------------------------------------------------------------------------
103 --  Function prototypes
104 ----------------------------------------------------------------------------*/
105 
106 static Widget
107   createMsgWindow( MSG_REC_REF        msg_win_ref,
108                    XIT_MSW_LABEL_REC  *labels );
109 
110 static void
111   clearCB( Widget       widget,
112            MSG_REC_REF  msg_win_ref,
113            XtPointer    call_data );
114 
115 static void
116   closeCB( Widget       widget,
117            MSG_REC_REF  msg_win_ref,
118            XtPointer    call_data );
119 
120 static void
121   destroyCB( Widget       widget,
122              MSG_REC_REF  msg_win_ref,
123              XtPointer    call_data );
124 
125 
126 
127 /*----------------------------------------------------------------------------
128 --  Functions
129 ----------------------------------------------------------------------------*/
130 
131 XIT_MSW_HANDLE
xitCreateMsgWindow(Widget parent,int max_messages,char * log_file,XIT_MSW_LABEL_REC * labels)132   xitCreateMsgWindow( Widget             parent,
133                       int                max_messages,
134                       char               *log_file,
135                       XIT_MSW_LABEL_REC  *labels )
136 {
137 
138   /* Variables. */
139   MSG_REC_REF  msg_win_ref;
140 
141 
142   /* Code. */
143 
144   /* Create and initialize our private data. */
145   msg_win_ref = SysNew( MSG_REC );
146   if( msg_win_ref == NULL )
147     return( NULL );
148 
149   msg_win_ref -> parentW      = parent;
150   msg_win_ref -> log_file     = NULL;
151   msg_win_ref -> max_msg      = max_messages;
152   msg_win_ref -> no_msg       = 0;
153   msg_win_ref -> selected_msg = 0;
154 
155   /* Any log file? */
156   if( log_file != NULL && *log_file != '\0' ) {
157     msg_win_ref -> log_file = SysNewString( log_file );
158   }
159 
160   /* Create the message window. */
161   msg_win_ref -> msgWinW = createMsgWindow( msg_win_ref, labels );
162 
163 
164   return( (XIT_MSW_HANDLE) msg_win_ref );
165 
166 } /* xitCreateMsgWindow */
167 
168 
169 /*----------------------------------------------------------------------*/
170 
171 void
xitMsgWinClearWindow(XIT_MSW_HANDLE msg_win_handle)172   xitMsgWinClearWindow( XIT_MSW_HANDLE  msg_win_handle )
173 {
174 
175   /* Variables. */
176   MSG_REC_REF  msg_win_ref;
177 
178 
179   /* Code. */
180 
181   if( msg_win_handle == NULL )
182     return;
183 
184   /* Our private data. */
185   msg_win_ref = (MSG_REC_REF) msg_win_handle;
186 
187 
188   /* Clear the window. */
189   clearCB( NULL, msg_win_ref, NULL );
190 
191 
192   return;
193 
194 } /* xitMsgWinClearWindow */
195 
196 
197 /*----------------------------------------------------------------------*/
198 
199 void
xitMsgWinDestroy(XIT_MSW_HANDLE msg_win_handle)200   xitMsgWinDestroy( XIT_MSW_HANDLE  msg_win_handle )
201 {
202 
203   /* Variables. */
204   MSG_REC_REF  msg_win_ref;
205 
206 
207   /* Code. */
208 
209   if( msg_win_handle == NULL )
210     return;
211 
212   /* Our private data. */
213   msg_win_ref = (MSG_REC_REF) msg_win_handle;
214 
215 
216   /* Destroy the window. */
217   XtDestroyWidget( msg_win_ref -> msgWinW );
218 
219 
220   return;
221 
222 } /* xitMsgWinDestroy */
223 
224 
225 /*----------------------------------------------------------------------*/
226 
227 void
xitMsgWinDisplayMessage(XIT_MSW_HANDLE msg_win_handle,char * msg,int msg_id)228   xitMsgWinDisplayMessage( XIT_MSW_HANDLE  msg_win_handle,
229                            char            *msg,
230                            int             msg_id )
231 {
232 
233   /* Variables. */
234   char            *char_ref;
235   char            *text_ref;
236   char            buffer[ 50 ];
237   char            msg_buf[ 1000 ];
238   Widget          mainW;
239   Widget          tempW;
240   XmTextPosition  position;
241   MSG_REC_REF     msg_win_ref;
242   TIM_TIME_REF    now;
243 
244 
245   /* Code. */
246 
247   if( msg_win_handle == NULL )
248     return;
249 
250   /* Our private data. */
251   msg_win_ref = (MSG_REC_REF) msg_win_handle;
252 
253 
254   now   = TimLocalTime( TimMakeTimeNow() );
255   mainW = XtNameToWidget( msg_win_ref -> msgWinW,
256                           "SysMsgWinTlBase.SysMsgWinTlFo" );
257 
258 
259   /* Build the message. */
260   msg_buf[ 0 ] = '\0';
261 
262   if( msg_id > 0 ) {
263     sprintf( buffer, "%2.2d  ", msg_id );
264     strcat( msg_buf, buffer );
265   }
266 
267   TimFormatDate( now, buffer, sizeof( buffer ) );
268   strcat( msg_buf, buffer );
269   strcat( msg_buf, " " );
270 
271   TimFormatTime( now, buffer, sizeof( buffer ) );
272   strcat( msg_buf, buffer );
273   strcat( msg_buf, "\n" );
274 
275   strcat( msg_buf, msg );
276 
277   if( msg_buf[ strlen( msg_buf ) - 1 ] != '\n' )
278     strcat( msg_buf, "\n" );
279   strcat( msg_buf, ">>\n" );
280 
281 
282   /* Write the message in the message window. */
283   tempW = XtNameToWidget( mainW, "MsgWinTxSW.MsgWinTx" );
284 
285   /* Remove the top message? */
286   if( msg_win_ref -> no_msg >= msg_win_ref -> max_msg ) {
287     text_ref = xitStringGetText( tempW );
288 
289     char_ref = strstr( text_ref, "\n>>\n" );
290     if( char_ref != NULL ) {
291       position = (XmTextPosition) (char_ref - text_ref + 3);
292       XmTextReplace( tempW, 0, position, "" );
293 
294       SysFree( text_ref );
295     }
296   }
297 
298   /* Add the new message. */
299   msg_win_ref -> no_msg++;
300 
301   text_ref = xitStringGetText( tempW );
302   position = (XmTextPosition) strlen( text_ref );
303   SysFree( text_ref );
304 
305   XmTextReplace( tempW, position, position, msg_buf );
306 
307   position = position + (XmTextPosition) strlen( msg_buf );
308   XmTextShowPosition( tempW, position );
309 
310 
311   /* Make sure the window is displayed. */
312   XtPopup( msg_win_ref -> msgWinW, XtGrabNone );
313 
314   XRaiseWindow( XtDisplay( msg_win_ref -> msgWinW ),
315                 XtWindow(  msg_win_ref -> msgWinW ) );
316 
317   XtMapWidget( msg_win_ref -> msgWinW );
318 
319 
320   return;
321 
322 } /* xitMsgWinDisplayMessage */
323 
324 
325 /*----------------------------------------------------------------------*/
326 
327 static Widget
createMsgWindow(MSG_REC_REF msg_win_ref,XIT_MSW_LABEL_REC * labels)328   createMsgWindow( MSG_REC_REF        msg_win_ref,
329                    XIT_MSW_LABEL_REC  *labels )
330 {
331 
332   /* Variables. */
333   Boolean   default_geometry = False;
334   int       index;
335   char      *char_ref;
336   Arg       args[ 10 ];
337   Cardinal  n;
338   Widget    controlBu[ 1 ];
339   Widget    dataLocalW[ 3 ];
340   Widget    sysMsgWinTl;
341   Widget    toplevel;
342   Widget    workFo;
343 
344   static XIT_PUSH_STRUCT control_def[] = {
345     { "ClosePb", "", "", True, NULL },
346   };
347 
348   static XIT_TEXT_STRUCT text_buffer_def[] = {
349     { "MsgWinTx", NULL, 2, True },
350   };
351 
352   static XIT_ACTION_AREA_ITEM  action_buttons[] = {
353     { NULL, NULL,    NULL },
354     { "",   closeCB, NULL },
355     { NULL, NULL,    NULL },
356   };
357 
358 
359   /* Code. */
360 
361   /* Set message strings. */
362   action_buttons[ 1 ].label = labels -> close_button;
363   action_buttons[ 1 ].data  = msg_win_ref;
364 
365   control_def[ 0 ].title = labels -> clear_button;
366 
367 
368   /* Create a form dialog with buttons. */
369   toplevel = xitGetToplevelWidget( msg_win_ref -> parentW );
370 
371   sysMsgWinTl = xitCreateToplevelDialog( toplevel, "SysMsgWinTl",
372                                          2, 0,
373                                          action_buttons,
374                                          XtNumber( action_buttons ) );
375 
376   n = 0;
377   XtSetArg( args[ n ], XmNtitle,    labels -> title ); n++;
378   XtSetArg( args[ n ], XmNiconName, labels -> title ); n++;
379   XtSetValues( sysMsgWinTl, args, n );
380 
381 
382   /* If no geometry defined, position in the middle of the screen. */
383   n = 0;
384   XtSetArg( args[ n ], XmNgeometry, &char_ref ); n++;
385   XtGetValues( sysMsgWinTl, args, n );
386 
387   if( char_ref != NULL && strpbrk( char_ref, "+-" ) != NULL )
388     default_geometry = False;
389 
390   if( default_geometry ) {
391     n = 0;
392     XtSetArg( args[ n ], XmNx,
393               WidthOfScreen( XtScreen( sysMsgWinTl ) ) / 2 ); n++;
394     XtSetArg( args[ n ], XmNy,
395               HeightOfScreen( XtScreen( sysMsgWinTl ) ) / 2 ); n++;
396     XtSetValues( sysMsgWinTl, args, n );
397   }
398 
399 
400   /* Pop down if this window is deleted. */
401   {
402     Atom  wm_delete_window;
403 
404     wm_delete_window = XmInternAtom( XtDisplay( sysMsgWinTl ),
405                                      "WM_DELETE_WINDOW", False );
406 
407     XmAddWMProtocols( sysMsgWinTl, &wm_delete_window, 1 );
408     XmAddWMProtocolCallback( sysMsgWinTl, wm_delete_window,
409                              (XtCallbackProc) closeCB,
410                              (XtPointer) msg_win_ref );
411   } /* block */
412 
413   XtAddCallback( sysMsgWinTl,  XmNdestroyCallback,
414                  (XtCallbackProc) destroyCB, (XtPointer) msg_win_ref );
415 
416 
417   /* Container for the contents of the window. */
418   workFo = XtNameToWidget( sysMsgWinTl, "SysMsgWinTlBase.SysMsgWinTlFo" );
419 
420 
421   /* Label for the message list. */
422   msgWinLa = xitCreateLabel( workFo, "MsgWinLa",
423                              labels -> list_label, XmALIGNMENT_BEGINNING );
424 
425   /* Text window with messages.. */
426   msgWinTx = xitCreateTextScrolled( workFo, &text_buffer_def[ 0 ] );
427 
428   n = 0;
429   XtSetArg( args[ n ], XmNeditable, False ); n++;
430   XtSetArg( args[ n ], XmNcursorPositionVisible, False ); n++;
431   XtSetValues( msgWinTx, args, n );
432 
433 
434   /* Control buttons. */
435   n = 0;
436   XtSetArg( args[ n ], XmNorientation,  XmHORIZONTAL ); n++;
437   XtSetArg( args[ n ], XmNspacing,      10 ); n++;
438   XtSetArg( args[ n ], XmNmarginHeight, 10 ); n++;
439   msgWinRc = XmCreateRowColumn( workFo, "MsgWinRc", args, n );
440 
441   for( index = 0; index < XtNumber( controlBu ); index++ )
442     controlBu[ index ] = xitCreatePushButton( msgWinRc,
443                                               &control_def[ index ] );
444 
445   XtAddCallback( controlBu[ 0 ], XmNactivateCallback,
446                  (XtCallbackProc) clearCB, (XtPointer) msg_win_ref );
447 
448   /* Put the elements together. */
449   xitAttachWidget( msgWinLa,
450                    XmATTACH_FORM, NULL, XmATTACH_FORM, NULL,
451                    XmATTACH_NONE, NULL, XmATTACH_NONE, NULL );
452   xitAttachWidget( XtParent( msgWinTx ),
453                    XmATTACH_WIDGET, msgWinLa, XmATTACH_FORM, NULL,
454                    XmATTACH_NONE,   NULL,     XmATTACH_NONE, NULL );
455   xitAttachWidget( msgWinRc,
456                    XmATTACH_WIDGET, XtParent( msgWinTx ), XmATTACH_FORM, NULL,
457                    XmATTACH_NONE,   NULL, XmATTACH_NONE, NULL );
458 
459 
460   /* Make sure there is enough space between the children. */
461   n = 0;
462   XtSetArg( args[ n ], XmNtopOffset,    5 ); n++;
463   XtSetArg( args[ n ], XmNleftOffset,   5 ); n++;
464   XtSetArg( args[ n ], XmNrightOffset,  5 ); n++;
465   XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++;
466   XtSetValues( msgWinLa,             args, n );
467   XtSetValues( XtParent( msgWinTx ), args, n );
468   XtSetValues( msgWinRc,             args, n );
469 
470   /* Manage the widgets. */
471   XtManageChildren( controlBu, XtNumber( controlBu ) );
472 
473   xitManageChildren( dataLocalW, XtNumber( dataLocalW ) );
474 
475 
476   /* Set the size of the window. */
477   xitSetSizeToplevelDialog( sysMsgWinTl, True );
478 
479   /* Make the final attachments. */
480   xitAttachWidget( msgWinRc,
481                    XmATTACH_NONE, NULL, XmATTACH_FORM, NULL,
482                    XmATTACH_NONE, NULL, XmATTACH_FORM, NULL );
483   xitAttachWidget( XtParent( msgWinTx ),
484                    XmATTACH_WIDGET, msgWinLa, XmATTACH_FORM,   NULL,
485                    XmATTACH_FORM,   NULL,     XmATTACH_WIDGET, msgWinRc );
486 
487 
488   return( sysMsgWinTl );
489 
490 } /* createMsgWindow */
491 
492 
493 /*----------------------------------------------------------------------*/
494 
495 static void
clearCB(Widget widget,MSG_REC_REF msg_win_ref,XtPointer call_data)496   clearCB( Widget       widget,
497            MSG_REC_REF  msg_win_ref,
498            XtPointer    call_data )
499 {
500 
501   /* Variables. */
502   Widget  mainW;
503   Widget  tempW;
504 
505 
506   /* Code. */
507 
508   mainW = XtNameToWidget( msg_win_ref -> msgWinW,
509                           "SysMsgWinTlBase.SysMsgWinTlFo" );
510 
511   /* Clear the message window (but leave the log file). */
512   tempW = XtNameToWidget( mainW, "MsgWinTxSW.MsgWinTx" );
513 
514   XmTextSetString( tempW, "" );
515 
516   msg_win_ref -> no_msg = 0;
517 
518 
519   return;
520 
521 } /* clearCB */
522 
523 
524 /*----------------------------------------------------------------------*/
525 
526 static void
closeCB(Widget widget,MSG_REC_REF msg_win_ref,XtPointer call_data)527   closeCB( Widget       widget,
528            MSG_REC_REF  msg_win_ref,
529            XtPointer    call_data )
530 {
531 
532   /* Code. */
533 
534   XtPopdown( msg_win_ref -> msgWinW );
535 
536 
537   return;
538 
539 } /* closeCB */
540 
541 
542 /*----------------------------------------------------------------------*/
543 
544 static void
destroyCB(Widget widget,MSG_REC_REF msg_win_ref,XtPointer call_data)545   destroyCB( Widget       widget,
546              MSG_REC_REF  msg_win_ref,
547              XtPointer    call_data )
548 {
549 
550   /* Code. */
551 
552   if( msg_win_ref -> log_file != NULL )
553     SysFree( msg_win_ref -> log_file );
554 
555   SysFree( msg_win_ref );
556 
557 
558   return;
559 
560 } /* destroyCB */
561