/* this file contains the code to put up misc messages: xe_msg(). * we also create and use system messages dialog. * the latter can be toggled on/off from the main menu. */ #include #include #include #include #include #include #include #include #include #include #include #include "xephem.h" extern char maincategory[]; static void msg_create_w (void); static void msg_erase_cb (Widget w, XtPointer client, XtPointer call); static void msg_close_cb (Widget w, XtPointer client, XtPointer call); static void msg_help_cb (Widget w, XtPointer client, XtPointer call); static void msg_add (char *msg); static void msg_scroll_down (void); static void alert_ok_cb (Widget w, XtPointer client, XtPointer call); static void xe_msg_alert (char *p); #define MINBELLSECS 3 /* min time between bell rings, seconds */ static Widget msg_w; /* system error log widget */ static Widget alert_w; /* system error message widget */ static Widget txt_w; /* scrolled text widget */ static int txtl; /* current length of text in txt_w */ /* called to force the scrolling message window to be up. */ void msg_manage() { if (!msg_w) msg_create_w(); XtPopup (msg_w, XtGrabNone); set_something (msg_w, XmNiconic, (XtArgVal)False); if (XtWindow(msg_w)) XMapRaised (XtDisplay(msg_w), XtWindow(msg_w)); } /* ring the bellm but avoid overdoing a lot of them */ void msg_bell() { static long lastbellt; long t; t = time (NULL); if (t - lastbellt >= MINBELLSECS) { XBell (XtDisplay(toplevel_w), 0); lastbellt = t; } } /* add the printf-style fmt[] to the message list. * if app_alert also show in an obnoxious app alert box. */ void xe_msg (int app_alert, char *fmt, ...) { char msg[2048]; va_list ap; /* explode */ va_start (ap, fmt); vsprintf (msg, fmt, ap); va_end (ap); /* if this is the first message, create the message box */ if (!msg_w) msg_create_w(); /* add to message list */ msg_add (msg); /* if an alert, display directly too */ if (app_alert && isUp(toplevel_w)) xe_msg_alert (msg); /* and ring the bell if turned on */ if (pref_get (PREF_MSG_BELL) == PREF_MSGBELL) msg_bell(); } /* called to put up or remove the watch cursor. */ void msg_cursor (c) Cursor c; { Window win; if (msg_w && (win = XtWindow(msg_w)) != 0) { Display *dsp = XtDisplay(msg_w); if (c) XDefineCursor (dsp, win, c); else XUndefineCursor (dsp, win); } if (alert_w && (win = XtWindow(alert_w)) != 0) { Display *dsp = XtDisplay(alert_w); if (c) XDefineCursor (dsp, win, c); else XUndefineCursor (dsp, win); } } /* create the message dialog */ static void msg_create_w() { static struct { char *name; void (*cb)(); char *tip; } cb[] = { {"Erase", msg_erase_cb, "Erase messages"}, {"Close", msg_close_cb, "Close this dialog"}, {"Help", msg_help_cb, "Get more information"}, }; Widget w, f_w; Arg args[20]; int i, n; /* make the help shell and form */ n = 0; XtSetArg (args[n], XmNcolormap, xe_cm); n++; XtSetArg (args[n], XmNtitle, "xephem System log"); n++; XtSetArg (args[n], XmNiconName, "Sys log"); n++; XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++; msg_w = XtCreatePopupShell ("SysLog", topLevelShellWidgetClass, toplevel_w, args, n); set_something (msg_w, XmNcolormap, (XtArgVal)xe_cm); sr_reg (msg_w, "XEphem*SysLog.x", maincategory, 0); sr_reg (msg_w, "XEphem*SysLog.y", maincategory, 0); n = 0; XtSetArg (args[n], XmNmarginHeight, 10); n++; XtSetArg (args[n], XmNmarginWidth, 10); n++; XtSetArg (args[n], XmNverticalSpacing, 10); n++; XtSetArg (args[n], XmNfractionBase, 12); n++; f_w = XmCreateForm (msg_w, "SLF", args, n); XtAddCallback (f_w, XmNhelpCallback, msg_help_cb, 0); XtManageChild (f_w); /* make the control buttons */ for (i = 0; i < XtNumber(cb); i++) { n = 0; XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNbottomOffset, 10); n++; XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++; XtSetArg (args[n], XmNleftPosition, 1 + 4*i); n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++; XtSetArg (args[n], XmNrightPosition, 3 + 4*i); n++; w = XmCreatePushButton (f_w, cb[i].name, args, n); XtAddCallback (w, XmNactivateCallback, cb[i].cb, NULL); wtip (w, cb[i].tip); XtManageChild (w); } /* make the scrolled text area to hold the messages */ n = 0; XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++; XtSetArg (args[n], XmNbottomOffset, 10); n++; XtSetArg (args[n], XmNbottomWidget, w); n++; XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; XtSetArg (args[n], XmNeditable, False); n++; XtSetArg (args[n], XmNcursorPositionVisible, False); n++; txt_w = XmCreateScrolledText (f_w, "Log", args, n); sr_reg (txt_w, "XEphem*SysLog*Log.columns", maincategory, 0); sr_reg (txt_w, "XEphem*SysLog*Log.rows", maincategory, 0); XtManageChild (txt_w); } /* callback from the erase pushbutton */ /* ARGSUSED */ static void msg_erase_cb (w, client, call) Widget w; XtPointer client; XtPointer call; { XmTextReplace (txt_w, 0, txtl, ""); txtl = 0; XFlush (XtDisplay(toplevel_w)); } /* callback from the close pushbutton */ /* ARGSUSED */ static void msg_close_cb (w, client, call) Widget w; XtPointer client; XtPointer call; { XtPopdown (msg_w); } /* callback from the help pushbutton */ /* ARGSUSED */ static void msg_help_cb (w, client, call) Widget w; XtPointer client; XtPointer call; { static char *msg[] = { "System messages" }; hlp_dialog ("SysLog", msg, sizeof(msg)/sizeof(msg[0])); } /* add msg to the txt_w widget. * Always set the vertical scroll bar to the extreme bottom. */ static void msg_add (msg) char *msg; { int l; l = strlen(msg); if (l == 0) return; XmTextReplace (txt_w, txtl, txtl, msg); txtl += l; if (msg[l-1] != '\n') msg_add ("\n"); else msg_scroll_down(); } /* make sure the text is scrolled to the bottom */ static void msg_scroll_down() { XmTextSetInsertionPosition (txt_w, txtl); } /* print a message, p, in shell message box */ static void xe_msg_alert (p) char *p; { static Widget apmsg_w; Arg args[20]; int n; if (!apmsg_w) { Widget w; /* Create shell. */ n = 0; XtSetArg (args[n], XmNallowShellResize, True); n++; XtSetArg (args[n], XmNcolormap, xe_cm); n++; XtSetArg (args[n], XmNtitle, "xephem Alert"); n++; XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++; alert_w = XtCreatePopupShell ("Alert", topLevelShellWidgetClass, toplevel_w, args, n); setup_icon (alert_w); XtAddCallback (alert_w, XmNpopupCallback, prompt_map_cb, NULL); set_something (alert_w, XmNcolormap, (XtArgVal)xe_cm); /* Create MessageBox . */ n = 0; XtSetArg (args[n], XmNresizePolicy, XmRESIZE_ANY); n++; XtSetArg (args[n], XmNdialogType, XmDIALOG_WARNING); n++; apmsg_w = XmCreateMessageBox (alert_w, "WB", args, n); XtAddCallback (apmsg_w, XmNokCallback, alert_ok_cb, NULL); XtManageChild (apmsg_w); w = XmMessageBoxGetChild (apmsg_w, XmDIALOG_CANCEL_BUTTON); XtUnmanageChild (w); w = XmMessageBoxGetChild (apmsg_w, XmDIALOG_HELP_BUTTON); XtUnmanageChild (w); } set_xmstring (apmsg_w, XmNmessageString, p); /* show it */ XtPopdown (alert_w); /* so Popup causes position and raise */ XtPopup (alert_w, XtGrabNone); set_something (alert_w, XmNiconic, (XtArgVal)False); /* make sure it's up because we are occasionally used when the main * loop might not run for a while */ XmUpdateDisplay (toplevel_w); XSync (XtDisplay(toplevel_w), False); } /* callback from the alert message box ok pushbutton */ /* ARGSUSED */ static void alert_ok_cb (w, client, call) Widget w; XtPointer client; XtPointer call; { XtPopdown (alert_w); }