📄 misc.c
字号:
/*** GetIntText, GetFloatText, GetIntTextWarn, GetFloatTextWarn**** Get the text of a motif text widget as an integer or floating point number.** The functions will return TEXT_READ_OK of the value was read correctly.** If not, they will return either TEXT_IS_BLANK, or TEXT_NOT_NUMBER. The** GetIntTextWarn and GetFloatTextWarn will display a dialog warning the** user that the value could not be read. The argument fieldName is used** in the dialog to help the user identify where the problem is. Set** warnBlank to true if a blank field is also considered an error.*/int GetFloatText(Widget text, double *value){ char *strValue, *endPtr; int retVal; strValue = XmTextGetString(text); /* Get Value */ removeWhiteSpace(strValue); /* Remove blanks and tabs */ *value = strtod(strValue, &endPtr); /* Convert string to double */ if (strlen(strValue) == 0) /* String is empty */ retVal = TEXT_IS_BLANK; else if (*endPtr != '\0') /* Whole string not parsed */ retVal = TEXT_NOT_NUMBER; else retVal = TEXT_READ_OK; XtFree(strValue); return retVal;}int GetIntText(Widget text, int *value){ char *strValue, *endPtr; int retVal; strValue = XmTextGetString(text); /* Get Value */ removeWhiteSpace(strValue); /* Remove blanks and tabs */ *value = strtol(strValue, &endPtr, 10); /* Convert string to long */ if (strlen(strValue) == 0) /* String is empty */ retVal = TEXT_IS_BLANK; else if (*endPtr != '\0') /* Whole string not parsed */ retVal = TEXT_NOT_NUMBER; else retVal = TEXT_READ_OK; XtFree(strValue); return retVal;}int GetFloatTextWarn(Widget text, double *value, const char *fieldName, int warnBlank){ int result; char *valueStr; result = GetFloatText(text, value); if (result == TEXT_READ_OK || (result == TEXT_IS_BLANK && !warnBlank)) return result; valueStr = XmTextGetString(text); if (result == TEXT_IS_BLANK) { DialogF(DF_ERR, text, 1, "Warning", "Please supply %s value", "Dismiss", fieldName); } else /* TEXT_NOT_NUMBER */ { DialogF (DF_ERR, text, 1, "Warning", "Can't read %s value: \"%s\"", "Dismiss", fieldName, valueStr); } XtFree(valueStr); return result;}int GetIntTextWarn(Widget text, int *value, const char *fieldName, int warnBlank){ int result; char *valueStr; result = GetIntText(text, value); if (result == TEXT_READ_OK || (result == TEXT_IS_BLANK && !warnBlank)) return result; valueStr = XmTextGetString(text); if (result == TEXT_IS_BLANK) { DialogF (DF_ERR, text, 1, "Warning", "Please supply a value for %s", "Dismiss", fieldName); } else /* TEXT_NOT_NUMBER */ { DialogF (DF_ERR, text, 1, "Warning", "Can't read integer value \"%s\" in %s", "Dismiss", valueStr, fieldName); } XtFree(valueStr); return result;}int TextWidgetIsBlank(Widget textW){ char *str; int retVal; str = XmTextGetString(textW); removeWhiteSpace(str); retVal = *str == '\0'; XtFree(str); return retVal;}/*** Turn a multi-line editing text widget into a fake single line text area** by disabling the translation for Return. This is a way to give users** extra space, by allowing wrapping, but still prohibiting newlines.** (SINGLE_LINE_EDIT mode can't be used, in this case, because it forces** the widget to be one line high).*/void MakeSingleLineTextW(Widget textW){ static XtTranslations noReturnTable = NULL; static char *noReturnTranslations = "<Key>Return: activate()\n"; if (noReturnTable == NULL) noReturnTable = XtParseTranslationTable(noReturnTranslations); XtOverrideTranslations(textW, noReturnTable);}/*** Add up-arrow/down-arrow recall to a single line text field. When user** presses up-arrow, string is cleared and recent entries are presented,** moving to older ones as each successive up-arrow is pressed. Down-arrow** moves to more recent ones, final down-arrow clears the field. Associated** routine, AddToHistoryList, makes maintaining a history list easier.**** Arguments are the widget, and pointers to the history list and number of** items, which are expected to change periodically.*/void AddHistoryToTextWidget(Widget textW, char ***historyList, int *nItems){ histInfo *histData; /* create a data structure for passing history info to the callbacks */ histData = (histInfo *)XtMalloc(sizeof(histInfo)); histData->list = historyList; histData->nItems = nItems; histData->index = -1; /* Add an event handler for handling up/down arrow events */ XtAddEventHandler(textW, KeyPressMask, False, (XtEventHandler)histArrowKeyEH, histData); /* Add a destroy callback for freeing history data structure */ XtAddCallback(textW, XmNdestroyCallback, histDestroyCB, histData);}static void histDestroyCB(Widget w, XtPointer clientData, XtPointer callData){ XtFree((char *)clientData);}static void histArrowKeyEH(Widget w, XtPointer callData, XEvent *event, Boolean *continueDispatch){ histInfo *histData = (histInfo *)callData; KeySym keysym = XLookupKeysym((XKeyEvent *)event, 0); /* only process up and down arrow keys */ if (keysym != XK_Up && keysym != XK_Down) return; /* increment or decrement the index depending on which arrow was pressed */ histData->index += (keysym == XK_Up) ? 1 : -1; /* if the index is out of range, beep, fix it up, and return */ if (histData->index < -1) { histData->index = -1; XBell(XtDisplay(w), 0); return; } if (histData->index >= *histData->nItems) { histData->index = *histData->nItems - 1; XBell(XtDisplay(w), 0); return; } /* Change the text field contents */ XmTextSetString(w, histData->index == -1 ? "" : (*histData->list)[histData->index]);}/*** Copies a string on to the end of history list, which may be reallocated** to make room. If historyList grows beyond its internally set boundary** for size (HISTORY_LIST_MAX), it is trimmed back to a smaller size** (HISTORY_LIST_TRIM_TO). Before adding to the list, checks if the item** is a duplicate of the last item. If so, it is not added.*/ void AddToHistoryList(char *newItem, char ***historyList, int *nItems){ char **newList; int i; if (*nItems != 0 && !strcmp(newItem, **historyList)) return; if (*nItems == HISTORY_LIST_MAX) { for (i=HISTORY_LIST_TRIM_TO; i<HISTORY_LIST_MAX; i++) XtFree((*historyList)[i]); *nItems = HISTORY_LIST_TRIM_TO; } newList = (char **)XtMalloc(sizeof(char *) * (*nItems + 1)); for (i=0; i < *nItems; i++) newList[i+1] = (*historyList)[i]; if (*nItems != 0 && *historyList != NULL) XtFree((char *)*historyList); (*nItems)++; newList[0] = XtNewString(newItem); *historyList = newList;}/* * PasswordText - routine to add a callback to any text widget so that all * text typed by the user is echoed with asterisks, allowing * a password to be typed in without being seen. * * parameters: w - text widget to add the callback to * passTxt - pointer to a string created by caller of this routine. * **NOTE** The length of this string should be one * greater than the maximum specified by XmNmaxLength. * This string is set to empty just before the callback * is added. */void PasswordText(Widget w, char *passTxt){ passTxt[0] = '\0'; XtAddCallback(w, XmNmodifyVerifyCallback, (XtCallbackProc)passwdCB,passTxt);}/*** BeginWait/EndWait**** Display/Remove a watch cursor over topCursorWidget and its descendents*/void BeginWait(Widget topCursorWidget){ Display *display = XtDisplay(topCursorWidget); Pixmap pixmap; Pixmap maskPixmap; XColor xcolors[2]; static Cursor waitCursor = 0; /* if the watch cursor hasn't been created yet, create it */ if (!waitCursor) { pixmap = XCreateBitmapFromData(display, DefaultRootWindow(display), (char *)watch_bits, watch_width, watch_height); maskPixmap = XCreateBitmapFromData(display, DefaultRootWindow(display), (char *)watch_mask_bits, watch_width, watch_height); xcolors[0].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(display)); xcolors[1].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(display)); XQueryColors(display, DefaultColormapOfScreen( DefaultScreenOfDisplay(display)), xcolors, 2); waitCursor = XCreatePixmapCursor(display, pixmap, maskPixmap, &xcolors[0], &xcolors[1], watch_x_hot, watch_y_hot); XFreePixmap(display, pixmap); XFreePixmap(display, maskPixmap); } /* display the cursor */ XDefineCursor(display, XtWindow(topCursorWidget), waitCursor);}void BusyWait(Widget widget){#ifdef __unix__ static const int timeout = 100000; /* 1/10 sec = 100 ms = 100,000 us */ static struct timeval last = { 0, 0 }; struct timeval current; gettimeofday(¤t, NULL); if ((current.tv_sec != last.tv_sec) || (current.tv_usec - last.tv_usec > timeout)) { XmUpdateDisplay(widget); last = current; } #else static time_t last = 0; time_t current; time(¤t); if (difftime(current, last) > 0) { XmUpdateDisplay(widget); last = current; }#endif}void EndWait(Widget topCursorWidget){ XUndefineCursor(XtDisplay(topCursorWidget), XtWindow(topCursorWidget));}/*** Create an X window geometry string from width, height, x, and y values.** This is a complement to the X routine XParseGeometry, and uses the same** bitmask values (XValue, YValue, WidthValue, HeightValue, XNegative, and** YNegative) as defined in <X11/Xutil.h> and documented under XParseGeometry.** It expects a string of at least MAX_GEOMETRY_STRING_LEN in which to write** result. Note that in a geometry string, it is not possible to supply a y** position without an x position. Also note that the X/YNegative flags** mean "add a '-' and negate the value" which is kind of odd.*/void CreateGeometryString(char *string, int x, int y, int width, int height, int bitmask){ char *ptr = string; int nChars; if (bitmask & WidthValue) { sprintf(ptr, "%d%n", width, &nChars); ptr += nChars; } if (bitmask & HeightValue) { sprintf(ptr, "x%d%n", height, &nChars); ptr += nChars; } if (bitmask & XValue) { if (bitmask & XNegative) sprintf(ptr, "-%d%n", -x, &nChars); else sprintf(ptr, "+%d%n", x, &nChars); ptr += nChars; } if (bitmask & YValue) { if (bitmask & YNegative) sprintf(ptr, "-%d%n", -y, &nChars); else sprintf(ptr, "+%d%n", y, &nChars); ptr += nChars; } *ptr = '\0';}/* *//* passwdCB: callback routine added by PasswordText routine. This routine *//* echoes each character typed as an asterisk (*) and a few other *//* necessary things so that the password typed in is not visible *//* */static void passwdCB(Widget w, char * passTxt, XmTextVerifyCallbackStruct *txtVerStr)/* XmTextVerifyCallbackStruct: *//* int reason; should be XmCR_MODIFYING_TEXT_VALUE *//* XEvent *event; points to XEvent that triggered the callback *//* Boolean doit; indicates whether action should be performed; setting *//* this to false negates the action *//* long currInsert, current position of insert cursor *//* newInsert; position user attempts to position the insert cursor *//* long startPos, starting position of the text to modify *//* endPos; ending position of the text to modify *//* XmTextBlock text; *//* XmTextBlock (used to pass text around): *//* char *ptr; points to text to be inserted *//* int length; Number of bytes (length) *//* XmTextFormat format; Representations format *//* XmTextFormat: either FMT8BIT or FMT16BIT */{ int numCharsTyped, i, j, pos; /* ensure text format is 8-bit characters */ if (txtVerStr->text->format != FMT8BIT) return; /* verify assumptions *//* if (txtVerStr->endPos < txtVerStr->startPos) fprintf(stderr, "User password callback error: endPos < startPos\n"); if (strlen(passTxt) == 0 && txtVerStr->endPos != 0) fprintf(stderr, "User password callback error: no txt, but end != 0\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -