/* $XConsortium: list.c /main/5 1995/07/15 20:46:14 drk $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #include #include #include #include #include "transfer.h" #define MAXT 100 #define DEFSTR "" extern TransferDataRec datums[]; extern unsigned int num_datums; static XmString GetItemValue(Widget); static char GetDisplayFormatFromType(Widget, Atom); static void setFormatAndMenu(char); static void SetDisplayTypeFromType(Widget, Atom); static Boolean global_set_defer = False; static Atom global_set_type_spec = None; static char global_read_format_spec = 'S'; static XtPointer global_value = NULL; static Atom global_type = None; static unsigned long global_length = 0; static int global_format = 8; static Boolean global_deferred = False; static int current_selected_item = -1; static Atom type = None; void SetType(Widget w, char *in, XtPointer ignore) { if (strlen(in) == 0) global_set_type_spec = XmeGetEncodingAtom(w); else if (strcmp(in, "NONE") == 0) global_set_type_spec = None; else global_set_type_spec = XInternAtom(XtDisplay(w), in, False); } /******************************************************************* * FindRightButton * * picks the correct button for the type option menu to display * note that the names are ATOMNAME_button, so it prepends a * '*' in front and '_button' after the name before looking up * the button. ******************************************************************/ static Widget FindRightButton(char* atom_string) { char buffer[80]; strcpy(buffer, "*b_"); strcat(buffer, atom_string); return(XtNameToWidget(toplevel, buffer)); } /********************************************************************* * ListSelectItem * * this is called when the user selects an item in the list. It takes * the type of the item and decides how to display it in the CSText * widget *********************************************************************/ void ListSelectItem(Widget w, XtPointer ignore, XmListCallbackStruct *listcb) { int index = listcb -> item_position; Atom XA_COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False), XA_PIXEL = XInternAtom(XtDisplay(w), "PIXEL", False), XA_LOCALE_TEXT = XmeGetEncodingAtom(w), XA_MOTIF_CS = XInternAtom(XtDisplay(w), XmS_MOTIF_COMPOUND_STRING, False), XA_MOTIF_RT = XInternAtom(XtDisplay(w), XmS_MOTIF_RENDER_TABLE, False); Widget mem = (Widget) NULL; char *targetname, *typename; XmString output, tmp; if (index < 1 || index > num_datums) return; index --; current_selected_item = index; global_type = type = datums[index].type; global_value = datums[index].value; global_length = datums[index].length; global_format = datums[index].format; global_deferred = datums[index].deferred; /* We create a big string and then place the string into the display field */ /* Target */ /* output = XmStringGenerate("Target: \t", NULL, NULL, NULL); */ output = XmStringCreateLocalized("Target: "); targetname = GetSafeAtom(XtDisplay(w), datums[index].target); if (targetname == NULL) targetname = XtNewString("Unknown"); tmp = XmStringCreateLocalized(targetname); XtFree(targetname); output = XmStringConcatAndFree(output, tmp); output = XmStringConcatAndFree(output, XmStringSeparatorCreate()); /* Type */ /* tmp = XmStringGenerate("Type: \t", NULL, NULL, NULL); */ tmp = XmStringCreateLocalized("Type: "); output = XmStringConcatAndFree(output, tmp); typename = GetSafeAtom(XtDisplay(w), datums[index].type); if (typename == NULL) typename = XtNewString("Unknown"); tmp = XmStringCreateLocalized(typename); XtFree(typename); output = XmStringConcatAndFree(output, tmp); output = XmStringConcatAndFree(output, XmStringSeparatorCreate()); /* Value display */ /* tmp = XmStringGenerate("Value: \t", NULL, NULL, NULL); */ tmp = XmStringCreateLocalized("Value: "); output = XmStringConcatAndFree(output, tmp); tmp = GetItemValue(text_display); output = XmStringConcatAndFree(output, tmp); /* Put value into display */ XmCSTextSetString(text_display, output); XmStringFree(output); } /********************************************************************* * EditItem * * This is called from the Properties or New menu item. If param * is 0 then this is a new item. *********************************************************************/ void EditItem(Widget w, int param, XtPointer ignore) { int index = current_selected_item; Atom XA_COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False), XA_PIXEL = XInternAtom(XtDisplay(w), "PIXEL", False), XA_LOCALE_TEXT = XmeGetEncodingAtom(w), XA_MOTIF_CS = XInternAtom(XtDisplay(w), XmS_MOTIF_COMPOUND_STRING, False), XA_MOTIF_RT = XInternAtom(XtDisplay(w), XmS_MOTIF_RENDER_TABLE, False); Widget mem = (Widget) NULL; char *targetname; XmString tmp; if (index >= num_datums) return; global_type = type = datums[index].type; global_value = datums[index].value; global_length = datums[index].length; global_format = datums[index].format; global_deferred = datums[index].deferred; global_set_defer = global_deferred; global_set_type_spec = global_type; global_read_format_spec = 'S'; if (param != 0) { /* Put name of target into display field */ targetname = GetSafeAtom(XtDisplay(w), datums[index].target); if (targetname == NULL) targetname = XtNewString("Unknown"); tmp = XmStringCreateLocalized(targetname); XmCSTextSetString(text2, tmp); XmStringFree(tmp); tmp = GetItemValue(text1); XmCSTextSetString(text1, tmp); XmStringFree(tmp); XtFree(targetname); SetDisplayTypeFromType(text1, global_type); global_read_format_spec = GetDisplayFormatFromType(text1, global_type); setFormatAndMenu(global_read_format_spec); XmToggleButtonGadgetSetState(defer, global_deferred, False); } else { tmp = XmStringCreateLocalized(""); XmCSTextSetString(text1, tmp); XmCSTextSetString(text2, tmp); SetDisplayTypeFromType(text1, XA_STRING); setFormatAndMenu('S'); XmToggleButtonGadgetSetState(defer, False, False); } } static char GetDisplayFormatFromType(Widget w, Atom type) { Atom XA_COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False), XA_PIXEL = XInternAtom(XtDisplay(w), "PIXEL", False), XA_LOCALE_TEXT = XmeGetEncodingAtom(w), XA_MOTIF_CS = XInternAtom(XtDisplay(w), XmS_MOTIF_COMPOUND_STRING, False), XA_MOTIF_RT = XInternAtom(XtDisplay(w), XmS_MOTIF_RENDER_TABLE, False); if (type == XA_ATOM || type == XInternAtom(XtDisplay(w), "ATOM_PAIR", False) || type == XA_INTEGER || type == XA_PIXEL || type == XInternAtom(XtDisplay(w), "SPAN", False)) { return('D'); } else if (type == XA_STRING) { return('S'); } else if (type == XA_COMPOUND_TEXT) { return('T'); } else if (type == XA_LOCALE_TEXT) { return('L'); } else if (type == XA_DRAWABLE || type == XA_WINDOW || type == XA_COLORMAP) { return('H'); } else if (type == XA_MOTIF_CS) { return('C'); } else if (type == XmeGetEncodingAtom(w)) { return('L'); } else { return('H'); } } static void SetDisplayTypeFromType(Widget w, Atom type) { Atom XA_COMPOUND_TEXT = XInternAtom(XtDisplay(w), XmSCOMPOUND_TEXT, False), XA_PIXEL = XInternAtom(XtDisplay(w), "PIXEL", False), XA_LOCALE_TEXT = XmeGetEncodingAtom(w), XA_MOTIF_CS = XInternAtom(XtDisplay(w), XmS_MOTIF_COMPOUND_STRING, False), XA_MOTIF_RT = XInternAtom(XtDisplay(w), XmS_MOTIF_RENDER_TABLE, False); Widget mem; if (type == XA_ATOM || type == XInternAtom(XtDisplay(w), "ATOM_PAIR", False)) { char str[80]; mem = FindRightButton("ATOM"); } else if (type == XA_INTEGER || type == XA_PIXEL) { if (type == XA_INTEGER) mem = FindRightButton("INTEGER"); else mem = FindRightButton("PIXEL"); } else if (type == XInternAtom(XtDisplay(w), "SPAN", False)) { mem = FindRightButton("SPAN"); } else if (type == XA_STRING) { mem = FindRightButton("STRING"); } else if (type == XA_COMPOUND_TEXT) { char *str; mem = FindRightButton("COMPOUND_TEXT"); } else if (type == XA_LOCALE_TEXT) { mem = FindRightButton("LOCALE_TEXT"); } else if (type == XA_DRAWABLE || type == XA_WINDOW || type == XA_COLORMAP) { if (type == XA_DRAWABLE) mem = FindRightButton("DRAWABLE"); else if (type == XA_COLORMAP) mem = FindRightButton("COLORMAP"); else mem = FindRightButton("WINDOW"); } else if (type == XA_MOTIF_CS) { mem = FindRightButton("_MOTIF_COMPOUND_STRING"); } else if (type == XmeGetEncodingAtom(w)) { mem = FindRightButton("LOCALE"); } else { char *typestring; char buffer[80]; mem = FindRightButton("unknown"); typestring = GetSafeAtom(XtDisplay(w), type); sprintf(buffer, "Unknown type %s (%d) found", typestring, type); XFree(typestring); } if (mem != (Widget) NULL) XtVaSetValues(typeOM, XmNmenuHistory, mem, NULL); } static void setFormatAndMenu(char in) { Widget mem = (Widget) NULL; if (in == 'S') { /* C String display */ mem = format_s; } else if (in == 'L') { /* Locale Text display */ mem = format_l; } else if (in == 'T') { /* Compound Text display */ mem = format_t; } else if (in == 'C') { /* Compound String display */ mem = format_cs; } else if (in == 'D') { /* Decimal display */ mem = format_id; } else { /* Hex display */ mem = format_ih; } SetFormat(NULL, in, NULL); if (mem != (Widget) NULL) XtVaSetValues(format_om, XmNmenuHistory, mem, NULL); } char *output_buffer = NULL; int output_buffer_max = 0; int output_buffer_current = 0; void ClearOB() { output_buffer_current = 0; if (output_buffer_max > 0) output_buffer[0] = 0; } void AppendOB(char *str) { int len; int i; len = strlen(str); while(len + output_buffer_current > output_buffer_max) { if (output_buffer_max == 0) { output_buffer_max = 256; output_buffer = XtMalloc(output_buffer_max); } else { output_buffer_max *= 2; output_buffer = XtRealloc(output_buffer, output_buffer_max); } } /* Copy data */ for(i = 0; i <= len; i++) output_buffer[output_buffer_current + i] = str[i]; /* Update end pointer */ output_buffer_current += len; } void SetFormat(Widget w, char in, XtPointer ignore) { int byte_length; XmString strtmp; global_read_format_spec = in; } static XmString GetItemValue(Widget w) { int byte_length; XmString strtmp; char in; byte_length = global_length * global_format / 8; in = GetDisplayFormatFromType(w, global_type); if (in == 'S') { /* C String display */ strtmp = XmStringCreateLocalized(global_value); } else if (in == 'L') { /* Locale Text display */ strtmp = XmStringCreateLocalized(global_value); } else if (in == 'T') { /* Compound Text display */ strtmp = XmCvtCTToXmString(global_value); } else if (in == 'C') { /* Compound String display */ strtmp = XmCvtByteStreamToXmString(global_value); } else if (in == 'D') { /* Decimal display */ int count, i; count = byte_length / 4; ClearOB(); for(i = 0; i < count; i++) { char buf[32]; sprintf(buf, "%d ", ((int *) global_value)[i]); AppendOB(buf); } strtmp = XmStringCreateLocalized(output_buffer); } else { /* Decimal display */ int count, i; count = byte_length / 4; ClearOB(); for(i = 0; i < count; i++) { char buf[32]; sprintf(buf, "0x%x ", ((int *) global_value)[i]); AppendOB(buf); } strtmp = XmStringCreateLocalized(output_buffer); } return(strtmp); } /******************************************************************* * SetValue * * No, it's not a widget method. This SetValue implements an action * which takes the current value in the interface and stores it away * for that particular target. This allows arbitrary data to be stored * into the data array for later transfer. *******************************************************************/ void SetValue(Widget widget, char *ignore, XmAnyCallbackStruct *callback_data) { XmString value; XmString target_name; char *type_widget_name; char *display_format_widget_name; char *target_string; Widget mem_history; Arg args[1]; int index; int base; Atom target; target_name = XmCSTextGetString(text2); value = XmCSTextGetString(text1); if (global_set_type_spec == None) return; /* Get the target string from the XmString */ target_string = ConvertXmStringToString(target_name); target = XInternAtom(XtDisplay(widget), target_string, False); XtFree(target_string); /* Find the index of this target, or add it to the end */ for(index = 0; index < num_datums; index++) if (datums[index].target == target) break; /* Add to the end, if this is a new target */ if (index == num_datums) { XmListAddItemUnselected(list, target_name, 0); datums[index].target = target; num_datums++; } /* Handle deferred */ if (datums[index].deferred != global_set_defer) { XmString new_item[1]; datums[index].deferred = global_set_defer; if (datums[index].deferred) { char *buffer; buffer = XtMalloc(strlen(target_string) + 2 + strlen(DEFSTR)); strcpy(buffer, target_string); strcat(buffer, "\t"); strcat(buffer, DEFSTR); new_item[0] = XmStringGenerate(buffer, NULL, XmCHARSET_TEXT, NULL); XtFree(buffer); } else new_item[0] = XmStringCopy(target_name); XmListReplaceItemsPos(list, new_item, 1, index + 1); XmListSelectPos(list, index + 1, False); XmStringFree(new_item[0]); } datums[index].type = global_set_type_spec; /* Convert the value */ if (global_read_format_spec == 'S') { datums[index].value = ConvertXmStringToString(value); if (datums[index].value != NULL) { datums[index].length = strlen(datums[index].value); } else { datums[index].length = 0; } datums[index].format = 8; } else if (global_read_format_spec == 'L') { char *ctext; char *ltext = NULL; Atom COMPOUND_TEXT = XInternAtom(XtDisplay(widget), XmSCOMPOUND_TEXT, False); XTextProperty text_prop; int status; char ** values; int num_values = 0; int malloc_size = 0; int i; ctext = XmCvtXmStringToCT(value); text_prop.value = (unsigned char *) ctext; text_prop.encoding = COMPOUND_TEXT; text_prop.format = 8; text_prop.nitems = strlen(ctext); status = XmbTextPropertyToTextList(XtDisplay(widget), &text_prop, &values, &num_values); XtFree(ctext); if (num_values) { for (i = 0; i < num_values ; i++) malloc_size += strlen(values[i]); ltext = XtMalloc ((unsigned) malloc_size + 1); ltext[0] = '\0'; for (i = 0; i < num_values ; i++) strcat(ltext, values[i]); XFreeStringList(values); } else { ltext = XtNewString(""); } datums[index].value = ltext; datums[index].length = malloc_size; datums[index].format = 8; } else if (global_read_format_spec == 'T') { datums[index].value = XmCvtXmStringToCT(value); if (datums[index].value != NULL) { datums[index].length = strlen(datums[index].value); } else { datums[index].length = 0; } datums[index].format = 8; } else if (global_read_format_spec == 'C') { datums[index].length = XmCvtXmStringToByteStream(value, (unsigned char **) &datums[index].value); datums[index].format = 8; } else if (global_read_format_spec == 'D' || global_read_format_spec == 'H') { /* Doesn't matter, the numbers contain the base information. We assume a string with whitespace separating the values. */ int max_values = 5; long *array = (long *) XtMalloc(sizeof(long) * max_values); int count = 0; char *convert; char *current; char *end; Boolean done = False; convert = ConvertXmStringToString(value); current = convert; if (global_read_format_spec == 'H') base = 16; else base = 0; while(! done) { /* Realloc array if getting too big */ if (count >= max_values) { max_values += 5; array = (long *) XtRealloc((char*) array, sizeof(long) * max_values); } if (current == 0) break; /* Now grab the next number */ array[count++] = strtol(current, &end, base); if (current == end || errno == ERANGE) { done = True; count--; } else current = end; } datums[index].value = (XtPointer) array; datums[index].length = count; datums[index].format = 32; } XmStringFree(target_name); XmStringFree(value); XmListSelectPos(list, index + 1, True); } /******************************************************************* * RemoveValue * * This removes an element from the data array. *******************************************************************/ void RemoveValue(Widget widget, char *ignore, XmAnyCallbackStruct *callback_data) { if (current_selected_item < 0 || current_selected_item >= num_datums) { XBell(XtDisplay(widget), 100); } else { int i; /* Free current value pointed at */ XtFree(datums[current_selected_item].value); num_datums--; /* Remove item from internal list */ for(i = current_selected_item; i < num_datums; i++) datums[i] = datums[i + 1]; /* Remove from screen display */ XmListDeletePos(list, current_selected_item + 1); /* Now update the display with the new value */ if (current_selected_item < num_datums) XmListSelectPos(list, current_selected_item + 1, True); else if (num_datums > 0) XmListSelectPos(list, current_selected_item, True); } } void deferCB(Widget widget, char *ignore, XmToggleButtonCallbackStruct *callback_data) { char *targetname; XmString new_item[1]; global_set_defer = callback_data -> set; } XmParseMapping table[2]; int table_size = -1; char* ConvertXmStringToString(XmString xmstr) { char *rvalue; if (table_size < 0) { XmString tmp; int nargs; Arg args[10]; table_size = 0; tmp = XmStringComponentCreate(XmSTRING_COMPONENT_TAB, 0, NULL); nargs = 0; XtSetArg(args[nargs], XmNincludeStatus, XmINSERT), nargs++; XtSetArg(args[nargs], XmNsubstitute, tmp), nargs++; XtSetArg(args[nargs], XmNpattern, "\t"), nargs++; table[table_size++] = XmParseMappingCreate(args, nargs); XmStringFree(tmp); tmp = XmStringSeparatorCreate(); nargs = 0; XtSetArg(args[nargs], XmNincludeStatus, XmINSERT), nargs++; XtSetArg(args[nargs], XmNsubstitute, tmp), nargs++; XtSetArg(args[nargs], XmNpattern, "\n"), nargs++; table[table_size++] = XmParseMappingCreate(args, nargs); XmStringFree(tmp); } rvalue = (char *) XmStringUnparse(xmstr, NULL, XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT, table, table_size, XmOUTPUT_ALL); return(rvalue); }