/* This file is part of the FElt finite element analysis package. Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /************************************************************************ * File: outputdialog.c * * * * Description: This file contains the public and private function and * * type definitions for the output dialog box. * ************************************************************************/ # include # include # include # include # include # include # include "Layout.h" # include "OutputDialog.h" # include "TabGroup.h" # include "util.h" # if NeedVarargsPrototypes # include # define Va_start(a,b) va_start(a,b) # else # include # define Va_start(a,b) va_start(a) # endif # define MaxButtons 4 # define Waiting ((String) 1) struct output_dialog { Widget shell; Widget layout; Widget text; Widget button [MaxButtons]; Widget dummy; Cardinal num_buttons; XtCallbackProc callback; XtPointer client_data; String selected; }; /* Resources */ static Pixel highlight; static String layout_string = "\ vertical { \ 4 \ horizontal { \ 4 \ text <+inf -100% * +inf -100%> \ 4 \ } \ 4 \ horizontal { \ 4 \ button1 4 button2 4 button3 4 button4 4 \ 4 \ } \ 4 \ }"; static Arg color_args [ ] = { {XtNborderColor, (XtArgVal) &highlight}, }; static Arg layout_args [ ] = { {XtNlayout, (XtArgVal) NULL}, }; static Arg text_args [ ] = { {XtNeditType, (XtArgVal) XawtextRead}, {XtNwrap, (XtArgVal) XawtextWrapWord}, {XtNscrollVertical, (XtArgVal) XawtextScrollWhenNeeded}, {XtNborderWidth, (XtArgVal) 0}, {XtNwidth, (XtArgVal) 1024}, }; static Arg command_args [ ] = { {XtNlabel, (XtArgVal) ""}, }; /* Translations */ static String command_table = "Return: AutoRepeat(off) set()\n\ Return: AutoRepeat(saved) notify() unset()\n\ space: AutoRepeat(off) set()\n\ space: AutoRepeat(saved) notify() unset()\n\ Escape: OutputDialogDelete()"; static XtTranslations command_translations; /************************************************************************ * Function: Delete * * * * Description: An action procedure which is called when the dialog is * * to be deleted; calls the callback of the dummy widget. * ************************************************************************/ static void Delete (w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { while (XtClass (w) != transientShellWidgetClass) w = XtParent (w); w = XtNameToWidget (w, "layout.dummy"); XtCallCallbacks (w, XtNcallback, NULL); } /************************************************************************ * Function: Notify * * * * Description: Notifies the user through a callback or selection. * ************************************************************************/ static void Notify (w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { OutputDialog outputd; String label; outputd = (OutputDialog) client_data; label = strcmp (XtName (w), "dummy") ? GetLabelString (w) : NULL; if (outputd -> callback != NULL) outputd -> callback (w, outputd -> client_data, label); else outputd -> selected = label; } /************************************************************************ * Function: OutputDialogCreate * * * * Description: Creates and returns a new output dialog box. The * * dialog can be popped up using OutputDialogSelect() * * which forces the user to make a selection, or by using * * OutputialogPopUp() which will call a callback when a * * button is selected or the dialog is deleted. The * * dialog can then be popped down using OutputDialog- * * Popdown(). * ************************************************************************/ OutputDialog OutputDialogCreate (parent, name, buttons, num_buttons) Widget parent; String name; String *buttons; Cardinal num_buttons; { Arg args [1]; Widget group [MaxButtons + 1]; char buffer [32]; Cardinal i; OutputDialog outputd; XFontStruct *font; static XtAppContext app_context = NULL; static XtActionsRec actions [ ] = {{"OutputDialogDelete", Delete}}; /* Perform one time initialization. */ if (app_context == NULL) { app_context = XtWidgetToApplicationContext (parent); XtAppAddActions (app_context, actions, XtNumber (actions)); AddAutoRepeatAction (app_context); command_translations = XtParseTranslationTable (command_table); layout_args [0].value = StringToLayout (parent, layout_string); } /* Create the output dialog and its widgets. */ outputd = XtNew (struct output_dialog); outputd -> shell = XtCreatePopupShell (name, transientShellWidgetClass, parent, NULL, 0); outputd -> layout = XtCreateManagedWidget ("layout", layoutWidgetClass, outputd -> shell, layout_args, XtNumber (layout_args)); outputd -> text = XtCreateManagedWidget ("text", asciiTextWidgetClass, outputd -> layout, text_args, XtNumber (text_args)); outputd -> dummy = XtCreateWidget ("dummy", commandWidgetClass, outputd -> layout, NULL, 0); XtSetArg (args [0], XtNfont, &font); XtGetValues (outputd -> text, args, 1); XtSetArg (args [0], XtNfont, font); XtSetValues (outputd -> dummy, args, 1); XtSetArg (args [0], XtNdisplayCaret, False); XtSetValues (outputd -> text, args, 1); if (num_buttons > MaxButtons) num_buttons = MaxButtons; outputd -> num_buttons = num_buttons; for (i = 0; i < num_buttons; i ++) { sprintf (buffer, "button%u", i + 1); XtSetArg (command_args [0], XtNlabel, buttons [i]); outputd -> button [i] = XtCreateManagedWidget (XtNewString (buffer), commandWidgetClass, outputd -> layout, command_args, XtNumber (command_args)); group [i] = outputd -> button [i]; } /* Create a tab group for the output dialog. */ /* group [i] = outputd -> text; XtGetValues (outputd -> layout, color_args, XtNumber (color_args)); CreateTabGroup (outputd -> shell, group, num_buttons + 1, highlight, True); */ XtGetValues (outputd -> layout, color_args, XtNumber (color_args)); CreateTabGroup (outputd -> shell, group, num_buttons, highlight, True); XtRealizeWidget (outputd -> shell); /* Add the translations to each widget. */ AddDeleteWindowProtocol (outputd -> shell, "OutputDialogDelete()"); for (i = 0; i < num_buttons; i ++) XtOverrideTranslations (outputd -> button [i], command_translations); /* Add the necessary callbacks. */ XtAddCallback (outputd -> dummy, XtNcallback, Notify, outputd); for (i = 0; i < num_buttons; i ++) XtAddCallback (outputd -> button [i], XtNcallback, Notify, outputd); return outputd; } /************************************************************************ * Function: OutputDialogSelect * * * * Description: Pops up the output dialog with the specified shell * * title, sets the input focus to the preferred button, * * and waits until a selection is made or the dialog is * * deleted; answer will point to the selection or NULL if * * the dialog was deleted. * ************************************************************************/ String OutputDialogSelect (outputd, title, preferred) OutputDialog outputd; String title; String preferred; { XEvent event; XtAppContext app_context; OutputDialogPopup (outputd, title, preferred, NULL, NULL); outputd -> selected = Waiting; app_context = XtWidgetToApplicationContext (outputd -> shell); while (outputd -> selected == Waiting) { XtAppNextEvent (app_context, &event); XtDispatchEvent (&event); } OutputDialogPopdown (outputd); return outputd -> selected; } /************************************************************************ * Function: OutputDialogPopup * * * * Description: Pops up the output dialog with the specified shell * * title and sets the input focus to the preferred button. * * If the callback is not NULL then it will be called upon * * selection or deletion with the specified client data. * ************************************************************************/ void OutputDialogPopup (outputd, title, preferred, callback, client_data) OutputDialog outputd; String title; String preferred; XtCallbackProc callback; XtPointer client_data; { Arg args [2]; Cardinal i; XtSetArg (args [0], XtNtitle, title); XtSetArg (args [1], XtNiconName, title); XtSetValues (outputd -> shell, args, 2); outputd -> callback = callback; outputd -> client_data = client_data; for (i = 0; i < outputd -> num_buttons; i ++) if (!strcmp (GetLabelString (outputd -> button [i]), preferred)) SetFocus (outputd -> button [i]); XtPopup (outputd -> shell, callback == NULL ? XtGrabExclusive : XtGrabNone); } /************************************************************************ * Function: OutputDialogPopdown * * * * Description: Pops down the specified output dialog. * ************************************************************************/ void OutputDialogPopdown (outputd) OutputDialog outputd; { XtPopdown (outputd -> shell); } /************************************************************************ * Function: OutputDialogView * * * * Description: ... * ************************************************************************/ void OutputDialogView (outputd, file_name, max_lines, max_columns) OutputDialog outputd; String file_name; Cardinal max_lines; Cardinal max_columns; { Arg args [4]; Cardinal length; Cardinal num_lines; Cardinal num_columns; XFontStruct *font; Dimension width; Dimension height; FILE *fp; if ((fp = fopen (file_name, "r")) == NULL) return; num_lines = 0; num_columns = 0; while (fscanf (fp, " %*[^\n]%n%*[\n]", &length) != EOF) { if (length > num_columns) num_columns = length; num_lines ++; } fclose (fp); if (max_lines && num_lines > max_lines) num_lines = max_lines; if (max_columns && num_columns > max_columns) num_columns = max_columns; XtSetArg (args [0], XtNfont, &font); XtGetValues (outputd -> text, args, 1); width = font -> max_bounds.width; height = font -> max_bounds.ascent + font -> max_bounds.descent; XtSetArg (args [0], XtNtype, XawAsciiFile); XtSetArg (args [1], XtNstring, file_name); XtSetArg (args [2], XtNwidth, width * (num_columns + 1) + 22); XtSetArg (args [3], XtNheight, height * (num_lines + 1)); XtSetValues (outputd -> text, args, 4); } /************************************************************************ * Function: OutputDialogPrintf * * * * Description: Uses OutputDialogVprintf() to simulate printf(). * ************************************************************************/ # if NeedVarargsPrototypes void OutputDialogPrintf (OutputDialog outputd, String format, ...) # else void OutputDialogPrintf (outputd, format, va_alist) OutputDialog outputd; String format; va_dcl # endif { va_list ap; Va_start (ap, format); OutputDialogVprintf (outputd, format, ap); va_end (ap); } /************************************************************************ * Function: OutputDialogVprintf * * * * Description: Acts like vprintf() only writes to the text widget. We * * need to force the size of the text widget so that the * * string can be seen. Ideally, we would query the * * preferred geometry of the text widget, but alas this * * doesn't work as the text widget doesn't have a * * preferred size since it just assumes that we'll use its * * built-in scrollbars and thus happily conforms to * * whatever size it has (yes, I know that resize should * * work but it doesn't seem to and it doesn't affect the * * preferred size). So instead we use the dummy widget to * * determine the proper size. This works since command * * (label) widgets return their preferred size and handle * * newlines correctly. Ideally, we would want to use a * * label widget rather than a text widget, but alas, the * * text widget allows cutting and pasting and more * * importantly allows a file to viewed efficiently. * ************************************************************************/ void OutputDialogVprintf (outputd, format, ap) OutputDialog outputd; String format; va_list ap; { Arg args [4]; char buffer [2048]; XtWidgetGeometry preferred; /* Set the label of the dummy widget to the desired string to that we can determine its preferred size. The text widget doesn't seem to have a preferred size so we have to do it this way. */ vsprintf (buffer, format, ap); SetLabelString (outputd -> dummy, buffer); XtQueryGeometry (outputd -> dummy, NULL, &preferred); XtSetArg (args [0], XtNtype, XawAsciiString); XtSetArg (args [1], XtNstring, buffer); XtSetArg (args [2], XtNwidth, preferred.width + 20); XtSetArg (args [3], XtNheight, preferred.height + 4); XtSetValues (outputd -> text, args, 4); } /************************************************************************ * Function: OutputDialogShell * * * * Description: Returns the shell widget of an output dialog. * ************************************************************************/ Widget OutputDialogShell (outputd) OutputDialog outputd; { return outputd -> shell; }