/***************************************************************************/
/***************************************************************************/
/* */
/* (c) 1995-1999. The Regents of the University of California. All */
/* rights reserved. */
/* */
/* This work was produced at the University of California, Lawrence */
/* Livermore National Laboratory (UC LLNL) under contract no. */
/* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */
/* (DOE) and The Regents of the University of California (University) */
/* for the operation of UC LLNL. Copyright is reserved to the */
/* University for purposes of controlled dissemination, */
/* commercialization through formal licensing, or other disposition */
/* under terms of Contract 48; DOE policies, regulations and orders; */
/* and U.S. statutes. The rights of the Federal Government are */
/* reserved under Contract 48 subject to the restrictions agreed upon */
/* by the DOE and University. */
/* */
/* */
/* DISCLAIMER */
/* */
/* This software was prepared as an account of work sponsored by an */
/* agency of the United States Government. Neither the United States */
/* Government nor the University of California nor any of their */
/* employees, makes any warranty, express or implied, or assumes any */
/* liability or responsibility for the accuracy, completeness, or */
/* usefulness of any information, apparatus, product, or process */
/* disclosed, or represents that its specific commercial products, */
/* process, or service by trade name, trademark, manufacturer, or */
/* otherwise, does not necessarily constitute or imply its */
/* endorsement, recommendation, or favoring by the United States */
/* Government or the University of California. The views and opinions */
/* of the authors expressed herein do not necessarily state or reflect */
/* those of the United States Government or the University of */
/* California, and shall not be used for advertising or product */
/* endorsement purposes. */
/* */
/* Permission to use, copy, modify and distribute this software and its */
/* documentation for any non-commercial purpose, without fee, is */
/* hereby granted, provided that the above copyright notice and this */
/* permission notice appear in all copies of the software and */
/* supporting documentation, and that all UC LLNL identification in */
/* the user interface remain unchanged. The title to copyright LLNL */
/* XDIR shall at all times remain with The Regents of the University */
/* of California and users agree to preserve same. Users seeking the */
/* right to make derivative works with LLNL XDIR for commercial */
/* purposes may obtain a license from the Lawrence Livermore National */
/* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */
/* Livermore, CA 94550. */
/* */
/***************************************************************************/
/***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <Xm/Form.h>
#include <Xm/Separator.h>
#include <Xm/SelectioB.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/List.h>
#include <Xm/TextF.h>
#include <Xm/Frame.h>
#include <Xm/PushB.h>
#include "list.h"
#include "str.h"
#define MAXVPLINE 200
#define V_IDENTIFIER "VIEWER:"
#define MAXQUESTION 1000
struct sl_struct *viewer_mappings;
extern Display *display;
extern int need_to_save_prefs;
extern int screen;
static struct {
Widget w_shell;
Widget w_form;
Widget w_controlArea;
Widget w_listLabel;
Widget w_list;
Widget w_extensionLabel;
Widget w_extension;
Widget w_commandLineLabel;
Widget w_commandLine;
Widget w_editFrame;
Widget w_editForm;
Widget w_addButton;
Widget w_replaceButton;
Widget w_deleteButton;
Widget w_messageFrame;
Widget w_messageRowcolumn;
Widget w_message1;
Widget w_message2;
Widget w_separator;
Widget w_actionArea;
Widget w_okButton;
Widget w_applyButton;
Widget w_cancelButton;
Widget w_helpButton;
} vprefs;
static char *vprefs_help[] = {
"This dialog enables you to control which file will be displayed",
"with which viewer, based on the file extension.\n",
"\n",
"A file to be viewed is first transferred to a temporary",
"directory and then, if necessary, is decompressed. The",
"file extension (e.g., \".gif\") is then examined to",
"determine which viewer the file is to be displayed in. There",
"are two types of viewers: the viewer built into LLNL XDIR",
"(which is suitable for displaying text files) and external",
"viewers (e.g., emacs for text and xv for graphics).\n",
"\n",
"Single-click on an entry in the extensions list to place",
"that extension and its associated command line into the",
"\"Extension\" and \"Viewer Command Line\" text fields,",
"respectively.\n",
"\n",
"An extension is a file suffix that begins with a period",
"(\".\"). A special entry in the extensions list, \"OTHERS\",",
"represents all files that do not have their extension listed",
"(including files with no extensions).\n",
"\n",
"The pattern \"<>\" in a command line is a placeholder for",
"the name of the file to be viewed. A blank command line",
"indicates that the built-in viewer is to be used.\n",
"\n",
"To add a new extension to the list, fill in the \"Extension\"",
"and \"Viewer Command Line\" text fields and press the ADD",
"button. If the text in \"Extension\" does not begin with",
"a period, one will be added. If the extension is already",
"in the list, it will be replaced.\n",
"\n",
"To replace the command line associated with an extension,",
"(1) single-click on the list item to select it, (2) edit",
"the command line, and (3) press the REPLACE button.\n",
"\n",
"To delete an extension from the list, single-click on the",
"list item to select it and then press the DELETE button. The",
"\"OTHERS\" entry cannot be deleted (but it's command line",
"can be replaced).\n",
"\n",
"Click the APPLY button to cause the new changes to take",
"effect. The OK button has the same effect as APPLY, but",
"the dialog is also closed. The CANCEL button undoes the",
"changes made since OK or APPLY were last pressed.\n",
"\n",
"The viewer preferences can be preserved across LLNL XDIR",
"sessions in a text file named \".xdirrc\" in the user's",
"home directory (select SAVE PREFERENCES in the main window's",
"OPTIONS menu).",
NULL
};
static char *default_mappings[] = {
".gif xv %s",
".jpg xv %s",
".c emacs %s",
".html netscape file:%s",
"OTHERS"
};
static int ndefault_mappings = XtNumber(default_mappings);
static struct sl_struct *temp_viewer_mappings;
static int initialized_vprefs = False;
static int vprefs_visible = False;
extern Widget w_toplev;
void cb_vprefs_cancel();
void cb_vprefs_help();
void cb_vprefs_add();
void cb_vprefs_delete();
void cb_vprefs_ok();
void cb_vprefs_apply();
void cb_vprefs_single_selection();
void cb_extension_modified();
void create_vprefs_window();
void apply_viewer_prefs();
void display_vprefs();
void did_user_forget();
struct sl_struct *create_array_list();
int compare_first_token();
struct sl_struct *create_null_array_list();
struct sl_struct *duplicate_array_list();
char *get_extension();
char *get_command_line();
char *cstring_to_text();
/*
* cb_viewer_preferences - Callback to pop up Viewer Preferences dialog.
*/
void
cb_viewer_preferences(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
/* Clear error flag */
raise_okflag();
/* Create the Viewer Preferences Dialog */
create_vprefs_window();
/* Make temporary copy of viewer/command line mappings */
temp_viewer_mappings = duplicate_array_list(viewer_mappings);
/* Update the Viewer Prefs dialog */
display_vprefs(viewer_mappings);
XmTextFieldSetString(vprefs.w_extension, "");
XmTextFieldSetString(vprefs.w_commandLine, "");
/* Select first item in extensions list */
XmListSelectPos(vprefs.w_list, 1, True);
/* Pop up viewer preferences window */
XtPopup(vprefs.w_shell, XtGrabNone);
add_dialog_to_list(vprefs.w_shell);
traverse_to_widget(vprefs.w_extension);
XMapRaised(display, XtWindow(vprefs.w_shell));
vprefs_visible = True;
}
/*
* create_vprefs_window - Create window for specifying which viewer
* should be used with each file type.
*/
void
create_vprefs_window()
{
Arg args[2];
int i;
/* Create dialog only once */
if (initialized_vprefs)
return;
initialized_vprefs = True;
/* Create toplevel shell for directory window */
vprefs.w_shell = XtVaCreatePopupShell("viewPrefs",
topLevelShellWidgetClass, w_toplev, NULL);
/* Attach custom icon */
attach_wm_icon(vprefs.w_shell);
/* Create form */
vprefs.w_form = XtVaCreateWidget("form", xmFormWidgetClass,
vprefs.w_shell, NULL);
/* Add callback for the WM_DELETE_WINDOW protocol */
add_wm_delete_window_cb(vprefs.w_shell, cb_vprefs_cancel, NULL, False);
/* Create form for action area */
vprefs.w_actionArea = XtVaCreateWidget(
"actionArea",
xmFormWidgetClass,
vprefs.w_form,
XmNmarginHeight, 10,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create OK pushbutton */
vprefs.w_okButton = XtVaCreateManagedWidget(
"okButton",
xmPushButtonWidgetClass,
vprefs.w_actionArea,
XmNdefaultButtonShadowThickness, 1,
XmNmarginHeight, 4,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 3,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 25,
NULL
);
XtAddCallback(vprefs.w_okButton, XmNactivateCallback, cb_vprefs_ok,
(XtPointer)NULL);
/* Create Apply pushbutton */
vprefs.w_applyButton = XtVaCreateManagedWidget(
"applyButton",
xmPushButtonWidgetClass,
vprefs.w_actionArea,
XmNdefaultButtonShadowThickness, 1,
XmNmarginHeight, 4,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 27,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 49,
NULL
);
XtAddCallback(vprefs.w_applyButton, XmNactivateCallback, cb_vprefs_apply,
(XtPointer)NULL);
/* Create Cancel pushbutton */
vprefs.w_cancelButton = XtVaCreateManagedWidget(
"cancelButton",
xmPushButtonWidgetClass,
vprefs.w_actionArea,
XmNdefaultButtonShadowThickness, 1,
XmNmarginHeight, 4,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 51,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 73,
NULL
);
XtAddCallback(vprefs.w_cancelButton, XmNactivateCallback, cb_vprefs_cancel,
(XtPointer)NULL);
XtVaSetValues(vprefs.w_form, XmNdefaultButton, vprefs.w_cancelButton,
NULL);
/* Create Help pushbutton */
vprefs.w_helpButton = XtVaCreateManagedWidget(
"helpButton",
xmPushButtonWidgetClass,
vprefs.w_actionArea,
XmNdefaultButtonShadowThickness, 1,
XmNmarginHeight, 4,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 75,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 97,
NULL
);
XtAddCallback(vprefs.w_helpButton, XmNactivateCallback, cb_vprefs_help,
(XtPointer)NULL);
XtManageChild(vprefs.w_actionArea);
/* Create separator */
vprefs.w_separator = XtVaCreateManagedWidget(
"separator",
xmSeparatorWidgetClass,
vprefs.w_form,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, vprefs.w_actionArea,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create form for control area */
vprefs.w_controlArea = XtVaCreateWidget(
"controlArea",
xmFormWidgetClass,
vprefs.w_form,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, vprefs.w_separator,
XmNmarginHeight, 10,
XmNmarginWidth, 10,
NULL
);
/* Create label for extension */
vprefs.w_extensionLabel = XtVaCreateManagedWidget(
"extensionLabel",
xmLabelWidgetClass,
vprefs.w_controlArea,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 45,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create textfield for extension */
vprefs.w_extension = XtVaCreateManagedWidget(
"extension",
xmTextFieldWidgetClass,
vprefs.w_controlArea,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_extensionLabel,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, vprefs.w_extensionLabel,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
XtAddCallback(vprefs.w_extension, XmNvalueChangedCallback,
cb_extension_modified, (XtPointer)NULL);
/* Create label for command line */
vprefs.w_commandLineLabel = XtVaCreateManagedWidget(
"commandLineLabel",
xmLabelWidgetClass,
vprefs.w_controlArea,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_extension,
XmNtopOffset, 10,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, vprefs.w_extension,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create textfield for command line */
vprefs.w_commandLine = XtVaCreateManagedWidget(
"commandLine",
xmTextFieldWidgetClass,
vprefs.w_controlArea,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_commandLineLabel,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, vprefs.w_commandLineLabel,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create frame for edit buttons */
vprefs.w_editFrame = XtVaCreateManagedWidget(
"editFrame",
xmFrameWidgetClass,
vprefs.w_controlArea,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_commandLine,
XmNtopOffset, 10,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, vprefs.w_commandLine,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create form for edit buttons */
vprefs.w_editForm = XtVaCreateManagedWidget(
"editForm",
xmFormWidgetClass,
vprefs.w_editFrame,
XmNmarginHeight, 2,
XmNmarginWidth, 2,
NULL
);
/* Create "Add" pushbutton */
vprefs.w_addButton = XtVaCreateManagedWidget(
"addButton",
xmPushButtonWidgetClass,
vprefs.w_editForm,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 50,
NULL
);
XtAddCallback(vprefs.w_addButton, XmNactivateCallback, cb_vprefs_add,
(XtPointer)NULL);
/* Create "Replace" pushbutton */
vprefs.w_replaceButton = XtVaCreateManagedWidget(
"replaceButton",
xmPushButtonWidgetClass,
vprefs.w_editForm,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 50,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
XtAddCallback(vprefs.w_replaceButton, XmNactivateCallback, cb_vprefs_add,
(XtPointer)NULL);
/* Create "Delete" pushbutton */
vprefs.w_deleteButton = XtVaCreateManagedWidget(
"deleteButton",
xmPushButtonWidgetClass,
vprefs.w_editForm,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_addButton,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 25,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 75,
NULL
);
XtAddCallback(vprefs.w_deleteButton, XmNactivateCallback, cb_vprefs_delete,
(XtPointer)NULL);
/* Create label for scrolled list of extensions */
vprefs.w_listLabel = XtVaCreateManagedWidget(
"listLabel",
xmLabelWidgetClass,
vprefs.w_controlArea,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL
);
/* Create scrolled list of extensions */
i = 0;
XtSetArg(args[i], XmNselectionPolicy, XmSINGLE_SELECT); i++;
XtSetArg(args[i], XmNlistSizePolicy, XmCONSTANT); i++;
vprefs.w_list = XmCreateScrolledList(vprefs.w_controlArea, "list", args, i);
XtVaSetValues(
XtParent(vprefs.w_list),
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_listLabel,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, vprefs.w_listLabel,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 40,
XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNbottomWidget, vprefs.w_editFrame,
NULL
);
XtManageChild(vprefs.w_list);
/* Add single-selection callback */
XtAddCallback(vprefs.w_list, XmNsingleSelectionCallback,
cb_vprefs_single_selection, (XtPointer)NULL);
/* Create frame for message */
vprefs.w_messageFrame = XtVaCreateManagedWidget(
"messageFrame",
xmFrameWidgetClass,
vprefs.w_controlArea,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, vprefs.w_editFrame,
XmNtopOffset, 15,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL
);
/* Create rowcolumn to hold warning message */
vprefs.w_messageRowcolumn = XtVaCreateManagedWidget(
"messageRowcolumn",
xmRowColumnWidgetClass,
vprefs.w_messageFrame,
NULL
);
/* Create label for first line of message */
vprefs.w_message1 = XtVaCreateManagedWidget(
"message1",
xmLabelWidgetClass,
vprefs.w_messageRowcolumn,
NULL
);
/* Create label for second line of message */
vprefs.w_message2 = XtVaCreateManagedWidget(
"message2",
xmLabelWidgetClass,
vprefs.w_messageRowcolumn,
NULL
);
XtManageChild(vprefs.w_controlArea);
XtManageChild(vprefs.w_form);
}
/*
* cb_vprefs_ok - Callback that applies current viewer preferences and
* then closes View Preferences dialog.
*/
void
cb_vprefs_ok(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
did_user_forget();
apply_viewer_prefs();
release_array_list(temp_viewer_mappings);
XtUnmapWidget(vprefs.w_shell);
vprefs_visible = False;
}
/*
* cb_vprefs_apply - Callback that applies current viewer preferences.
*/
void
cb_vprefs_apply(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
did_user_forget();
apply_viewer_prefs();
}
/*
* cb_vprefs_cancel - Callback that restores old viewer preferences
* and then the closes Viewer Preferences dialog.
*/
void
cb_vprefs_cancel(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
release_array_list(temp_viewer_mappings);
XtUnmapWidget(vprefs.w_shell);
vprefs_visible = False;
}
/*
* cb_vprefs_help - Callback that displays help info for the Viewer
* Preferences dialog.
*/
void
cb_vprefs_help(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
help_dialog(widget, False, "Viewer Preferences", vprefs_help);
}
/*
* add_to_list - Add extension/viewer pair to list. If an entry in the
* list has the same extension, it is first deleted.
*/
void
add_to_list()
{
char *command_line;
char *extension;
char *ext_command;
int i;
XmString string;
/* Get extension */
extension = get_extension();
if (strlen(extension) == 0)
fatal_error("Trouble in add_to_list()");
/* Get command line */
command_line = get_command_line();
/* Form viewer/command line pair */
ext_command = XtMalloc(strlen(extension)+strlen(command_line)+2);
strcpy(ext_command, extension);
if (strlen(command_line)) {
strcat(ext_command, " ");
strcat(ext_command, command_line);
}
/* Add to temporary mappings (but first check for existing extension) */
for (i=0; i<temp_viewer_mappings->nentries; i++)
if (!compare_first_token(ext_command,
temp_viewer_mappings->entries[i])) {
delete_from_array_list(&temp_viewer_mappings, i);
break;
}
add_to_array_list(&temp_viewer_mappings, ext_command);
XtFree(ext_command);
/* Sort and redisplay entries */
quicksort(temp_viewer_mappings->entries, temp_viewer_mappings->nentries,
compare_first_token);
display_vprefs(temp_viewer_mappings);
/* Select newly added item */
string = XmStringCreateSimple(extension);
XmListSelectItem(vprefs.w_list, string, True);
XmStringFree(string);
XtFree(extension);
XtFree(command_line);
}
/*
* cb_vprefs_add - Callback that adds new extension/viewer pair to list.
* If an entry in the list has the same extension, it
* is deleted.
*/
void
cb_vprefs_add(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
add_to_list();
}
/*
* cb_vprefs_delete - Callback that deletes new extension/viewer pair
* from list.
*/
void
cb_vprefs_delete(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
int *position_list;
int position_count;
int retval;
XmStringTable selected_items;
char *extension;
/* Get position of selected item */
retval = XmListGetSelectedPos(vprefs.w_list,&position_list,&position_count);
/* Sanity check */
XtVaGetValues(vprefs.w_list, XmNselectedItems, &selected_items, NULL);
extension = cstring_to_text(selected_items[0]);
if (!strcmp(extension, "OTHERS"))
fatal_error("Bug in cb_vprefs_delete()\n");
XtFree(extension);
/* Sanity check */
if (!retval || (position_count != 1))
fatal_error("Trouble in cb_vprefs_delete()");
/* Delete corresponding item from temporary viewer/command line list */
delete_from_array_list(&temp_viewer_mappings, position_list[0]-1);
/* Update the extensions list */
display_vprefs(temp_viewer_mappings);
/* Select first item */
XmListSelectPos(vprefs.w_list, 1, True);
}
/*
* apply_viewer_prefs - Set current viewer preferences to displayed values.
*/
void
apply_viewer_prefs()
{
need_to_save_prefs = True;
/* Replace current mappings with temporary mappings */
release_array_list(viewer_mappings);
viewer_mappings = duplicate_array_list(temp_viewer_mappings);
}
/*
* read_vprefs_from_file - Initializes current viewer preferences with
* values from .xdirrc (which is pointed to by
* "fp". If "fp" is NULL, then use default
* values.
*/
void
read_vprefs_from_file(fp)
FILE *fp;
{
char vprefs_line[MAXVPLINE+1];
char *q;
char *extension;
char *command_line;
char *ext_command;
int i;
int j;
int found_others = False;
/* Create empty list of mappings */
viewer_mappings = create_null_array_list();
/* Try to open viewer preferences file. If failure, use defaults */
if (fp == NULL) {
for (i=0; i<ndefault_mappings; i++) {
for (j=0; j<viewer_mappings->nentries; j++)
if (!compare_first_token(default_mappings[i],
viewer_mappings->entries[j])) {
delete_from_array_list(&viewer_mappings, j);
break;
}
add_to_array_list(&viewer_mappings, default_mappings[i]);
}
quicksort(viewer_mappings->entries, viewer_mappings->nentries,
compare_first_token);
return;
}
/* Process viewer preferences from file */
while (fgets(vprefs_line, MAXVPLINE+1, fp) != NULL) {
if (vprefs_line[strlen(vprefs_line)-1] != '\n')
continue;
if ((q=strtok(vprefs_line, " \t")) == NULL)
continue;
if (strcmp(q, V_IDENTIFIER))
continue;
if ((q=strtok(NULL, " \t\n")) == NULL)
continue;
if (*q != '.' && strcmp(q, "OTHERS"))
continue;
extension = XtNewString(q);
if ((q = strtok(NULL, "\n")) == NULL)
command_line = XtNewString("");
else {
while (isspace(*q))
q++;
for (i=strlen(q)-1; i>=0; i--)
if (isspace(q[i]))
q[i] = '\0';
else
break;
command_line = XtNewString(q);
}
if (!strcmp(extension, "OTHERS"))
found_others = True;
ext_command = XtMalloc(strlen(extension)+strlen(command_line)+2);
strcpy(ext_command, extension);
if (strlen(command_line)) {
strcat(ext_command, " ");
strcat(ext_command, command_line);
}
XtFree(extension);
XtFree(command_line);
for (j=0; j<viewer_mappings->nentries; j++)
if (!compare_first_token(ext_command,
viewer_mappings->entries[j])) {
delete_from_array_list(&viewer_mappings, j);
break;
}
add_to_array_list(&viewer_mappings, ext_command);
XtFree(ext_command);
}
/* Add viewer for unspecified extensions if not found in file */
if (!found_others)
add_to_array_list(&viewer_mappings, "OTHERS");
/* Sort array of mappings */
quicksort(viewer_mappings->entries, viewer_mappings->nentries,
compare_first_token);
}
/*
* compare_first_token - Compare two "string1" and "string2" by comparing
* their first whitespace-delimited tokens. Returns
* -1 if "string1" is less than "string2", 0 if
* "string1" equals "string2", and 1 if "string1"
* is greater than "string2". Each string is required
* to have at least one non-null token.
*/
compare_first_token(string1, string2)
char *string1;
char *string2;
{
char *token1;
char *token2;
char *temp_string1 = XtNewString(string1);
char *temp_string2 = XtNewString(string2);
int retval;
if ((token1 = strtok(temp_string1, " \t\n")) == NULL)
fatal_error("Trouble in compare_first_token()");
if ((token2 = strtok(temp_string2, " \t\n")) == NULL)
fatal_error("Trouble in compare_first_token()");
retval = strcmp(token1, token2);
XtFree(temp_string1);
XtFree(temp_string2);
return retval;
}
/*
* save_vprefs - Write current viewer preferences to .xdirrc using file
* pointer "fp".
*/
void
save_vprefs(fp)
FILE *fp;
{
int i;
for (i=0; i<viewer_mappings->nentries; i++)
fprintf(fp, "%s %s\n", V_IDENTIFIER, viewer_mappings->entries[i]);
}
/*
* display_vprefs - Update the Viewer Preferences dialog with the
* specified extension-to-viewer mappings "mappings".
*/
void
display_vprefs(mappings)
struct sl_struct *mappings;
{
char *temp_buf;
char *extension;
XmString string;
int i;
/* Update extensions list */
reset_list(vprefs.w_list);
for (i=0; i<mappings->nentries; i++) {
temp_buf = XtNewString(mappings->entries[i]);
extension = strtok(temp_buf, " ");
string = XmStringCreateSimple(extension);
XtFree(temp_buf);
XmListAddItem(vprefs.w_list, string, 0);
XmStringFree(string);
}
}
/*
* cb_vprefs_single_selection - This callback is invoked when an item
* in the extensions list is selected.
*/
void
cb_vprefs_single_selection(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
XmListCallbackStruct *cbs = (XmListCallbackStruct *)call_data;
int nselected_items;
char *ext_command;
char *ptr;
/* Don't let user deselect item */
XtVaGetValues(vprefs.w_list, XmNselectedItemCount, &nselected_items, NULL);
if (nselected_items == 0)
XmListSelectPos(vprefs.w_list, cbs->item_position, False);
/* Update text fields */
ext_command = XtNewString(
temp_viewer_mappings->entries[cbs->item_position-1]);
if ((ptr = strchr(ext_command, ' '))) {
*ptr++ = '\0';
XmTextFieldSetString(vprefs.w_commandLine, ptr);
} else
XmTextFieldSetString(vprefs.w_commandLine, "");
XmTextFieldSetString(vprefs.w_extension, ext_command);
/* Adjust sensitivity of Delete button */
if (strcmp(ext_command, "OTHERS"))
XtSetSensitive(vprefs.w_deleteButton, True);
else
XtSetSensitive(vprefs.w_deleteButton, False);
XtFree(ext_command);
}
/*
* get_extension - Returns the current value of the extension field with
* white space removed. If a leading period is absent,
* one is prepended (except for the case of "OTHERS").
* Caller should use XtFree() to release returned string.
*/
char *
get_extension()
{
char *extension;
char *text;
char *temp;
/* Process extension */
text = XmTextFieldGetString(vprefs.w_extension);
if ((temp = strtok(text, " \t")) == NULL) {
XtFree(text);
return XtNewString("");
}
if (temp[0] == '.' || !strcmp(temp, "OTHERS"))
extension = XtNewString(temp);
else {
extension = XtMalloc(strlen(temp)+2);
strcpy(extension, ".");
strcat(extension, temp);
}
XtFree(text);
return extension;
}
/*
* get_command_line - Returns the current value of the command line field
* with leading and trailing white space removed. Caller
* should use XtFree() to release returned string.
*/
char *
get_command_line()
{
char *command_line;
char *text;
int i;
int len;
/* Process command line */
text = XmTextFieldGetString(vprefs.w_commandLine);
for (i=strlen(text)-1; i>=0; i--)
if (isspace(text[i]))
text[i] = '\0';
else
break;
len = strlen(text);
for (i=0; i<len; i++)
if (!isspace(text[i]))
break;
if (i == len)
command_line = XtNewString("");
else
command_line = XtNewString(&text[i]);
XtFree(text);
return command_line;
}
/*
* cb_extension_modified - Callback that is invoked when the value of the
* extension field has changed. The purpose of
* this callback is to make the appropriate edit
* buttons selectable.
*/
void
cb_extension_modified(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
char *extension;
int i;
extension = get_extension();
/* Adjust sensitivity of edit buttons */
if (strlen(extension)) {
for (i=0; i<temp_viewer_mappings->nentries; i++)
if (!compare_first_token(extension,
temp_viewer_mappings->entries[i])) {
break;
}
if (i == temp_viewer_mappings->nentries) {
XtSetSensitive(vprefs.w_addButton, True);
XtSetSensitive(vprefs.w_replaceButton, False);
} else {
XtSetSensitive(vprefs.w_addButton, False);
XtSetSensitive(vprefs.w_replaceButton, True);
}
} else {
XtSetSensitive(vprefs.w_addButton, False);
XtSetSensitive(vprefs.w_replaceButton, False);
}
XtFree(extension);
}
/*
* did_user_forget - Make sure that user did not intend to press "Add"
* or "Replace" button.
*/
void
did_user_forget()
{
char *extension = get_extension();
char question[MAXQUESTION];
int i;
char *ptr;
char *command_line;
char *cmd_line;
/* No problem if extension is null */
if (strlen(extension) == 0) {
XtFree(extension);
return;
}
/* If extension is already in list, did user intend to replace? */
for (i=0; i<temp_viewer_mappings->nentries; i++)
if (!compare_first_token(extension, temp_viewer_mappings->entries[i])) {
command_line = get_command_line();
if ((ptr = strchr(temp_viewer_mappings->entries[i], ' '))) {
ptr++;
cmd_line = XtNewString(ptr);
} else
cmd_line = XtNewString("");
if (strcmp(command_line, cmd_line)) {
strcpy(question, "You edited the command line associated ");
strcat(question, "with an\nexisting extension, but did not ");
strcat(question, "press the \"Replace\"\nbutton.\n\n");
strcat(question, "Do you wish to replace the command line ");
strcat(question, "associated\nwith \"");
strcat(question, extension);
strcat(question, "\"?");
if (question_dialog(question, vprefs.w_shell))
add_to_list();
}
XtFree(command_line);
XtFree(cmd_line);
XtFree(extension);
return;
}
/* Extension is not in list, did user intend to add? */
strcpy(question, "You specified a new extension, but did not add it ");
strcat(question, "to the list.\n\nDo you wish to add \"");
strcat(question, extension);
strcat(question, "\" to the list?");
if (question_dialog(question, vprefs.w_shell))
add_to_list();
XtFree(extension);
}
/*
* iconify_vprefs_window - Iconify viewer preferences window.
*/
void
iconify_vprefs_window()
{
if (vprefs_visible)
XIconifyWindow(display, XtWindow(vprefs.w_shell), screen);
}
/*
* deiconify_vprefs_window - Deiconify viewer preferences window.
*/
void
deiconify_vprefs_window()
{
if (vprefs_visible)
XMapWindow(display, XtWindow(vprefs.w_shell));
}
syntax highlighted by Code2HTML, v. 0.9.1