diff options
Diffstat (limited to 'iup/src/mot/iupmot_text.c')
-rwxr-xr-x | iup/src/mot/iupmot_text.c | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/iup/src/mot/iupmot_text.c b/iup/src/mot/iupmot_text.c new file mode 100755 index 0000000..4a8f936 --- /dev/null +++ b/iup/src/mot/iupmot_text.c @@ -0,0 +1,1165 @@ +/** \file + * \brief Text Control + * + * See Copyright Notice in "iup.h" + */ + +#include <Xm/Xm.h> +#include <Xm/TextF.h> +#include <Xm/Text.h> +#include <Xm/ScrolledW.h> +#include <Xm/SpinB.h> +#include <X11/keysym.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> +#include <limits.h> + +#include "iup.h" +#include "iupcbs.h" + +#include "iup_object.h" +#include "iup_childtree.h" +#include "iup_attrib.h" +#include "iup_dialog.h" +#include "iup_str.h" +#include "iup_mask.h" +#include "iup_drv.h" +#include "iup_array.h" +#include "iup_text.h" + +#include "iupmot_drv.h" +#include "iupmot_color.h" + + +#ifndef XmIsSpinBox +#define XmIsSpinBox(w) XtIsSubclass(w, xmSpinBoxWidgetClass) +#endif + +#ifndef XmNwrap +#define XmNwrap "Nwrap" +#endif + +void iupdrvTextAddFormatTag(Ihandle* ih, Ihandle* formattag) +{ + (void)ih; + (void)formattag; +} + +void iupdrvTextAddSpin(int *w, int h) +{ + *w += h/2; +} + +void iupdrvTextAddBorders(int *w, int *h) +{ + int border_size = 2*5; + (*w) += border_size; + (*h) += border_size; +} + +static void motTextGetLinColFromPosition(const char *str, int pos, int *lin, int *col ) +{ + int i; + + *lin = 0; + *col = 0; + + for (i=0; i<pos; i++) + { + if (*str == '\n') + { + (*lin)++; + *col = 0; + } + else + (*col)++; + + str++; + } + + (*lin)++; /* IUP starts at 1 */ + (*col)++; +} + +static int motTextSetLinColToPosition(const char *str, int lin, int col) +{ + int pos=0, cur_lin=0, cur_col=0; + + lin--; /* IUP starts at 1 */ + col--; + + while (*str) + { + if (lin<=cur_lin && col<=cur_col) + break; + + if (*str == '\n') + { + cur_lin++; + cur_col = 0; + } + else + cur_col++; + + str++; + pos++; + } + + return pos; +} + +void iupdrvTextConvertLinColToPos(Ihandle* ih, int lin, int col, int *pos) +{ + char* str = XmTextGetString(ih->handle); + *pos = motTextSetLinColToPosition(str, lin, col); + XtFree(str); +} + +void iupdrvTextConvertPosToLinCol(Ihandle* ih, int pos, int *lin, int *col) +{ + char *str = XmTextGetString(ih->handle); + motTextGetLinColFromPosition(str, pos, lin, col); + XtFree(str); +} + +static int motTextConvertXYToPos(Ihandle* ih, int x, int y) +{ + return XmTextXYToPos(ih->handle, x, y); +} + + +/*******************************************************************************************/ + + +static int motTextSetPaddingAttrib(Ihandle* ih, const char* value) +{ + iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x'); + if (ih->handle) + { + XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding, + XmNmarginWidth, ih->data->horiz_padding, NULL); + } + return 0; +} + +static int motTextSetReadOnlyAttrib(Ihandle* ih, const char* value) +{ + XtVaSetValues(ih->handle, XmNeditable, iupStrBoolean(value)? False: True, NULL); + return 0; +} + +static char* motTextGetReadOnlyAttrib(Ihandle* ih) +{ + Boolean editable; + XtVaGetValues(ih->handle, XmNeditable, &editable, NULL); + if (editable) + return "YES"; + else + return "NO"; +} + +static int motTextSetInsertAttrib(Ihandle* ih, const char* value) +{ + if (!ih->handle) /* do not store the action before map */ + return 0; + if (!value) + return 0; + + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XmTextRemove(ih->handle); + XmTextInsert(ih->handle, XmTextGetInsertionPosition(ih->handle), (char*)value); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + + return 0; +} + +static int motTextSetSelectedTextAttrib(Ihandle* ih, const char* value) +{ + XmTextPosition start, end; + + if (!value) + return 0; + + if (XmTextGetSelectionPosition(ih->handle, &start, &end) && start!=end) + { + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XmTextReplace(ih->handle, start, end, (char*)value); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + + return 0; +} + +static char* motTextGetSelectedTextAttrib(Ihandle* ih) +{ + char* selectedtext = XmTextGetSelection(ih->handle); + char* str = iupStrGetMemoryCopy(selectedtext); + XtFree(selectedtext); + return str; +} + +static int motTextSetAppendAttrib(Ihandle* ih, const char* value) +{ + XmTextPosition pos; + if (!ih->handle) /* do not store the action before map */ + return 0; + pos = XmTextGetLastPosition(ih->handle); + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + if (ih->data->is_multiline && ih->data->append_newline) + XmTextInsert(ih->handle, pos, "\n"); + if (value) + XmTextInsert(ih->handle, pos+1, (char*)value); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + return 0; +} + +static int motTextSetSelectionAttrib(Ihandle* ih, const char* value) +{ + int start=1, end=1; + + if (!value || iupStrEqualNoCase(value, "NONE")) + { + XmTextClearSelection(ih->handle, CurrentTime); + return 0; + } + + if (iupStrEqualNoCase(value, "ALL")) + { + XmTextSetSelection(ih->handle, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(ih->handle), CurrentTime); + return 0; + } + + if (ih->data->is_multiline) + { + int lin_start=1, col_start=1, lin_end=1, col_end=1; + char *str; + + if (sscanf(value, "%d,%d:%d,%d", &lin_start, &col_start, &lin_end, &col_end)!=4) return 0; + if (lin_start<1 || col_start<1 || lin_end<1 || col_end<1) return 0; + + str = XmTextGetString(ih->handle); + start = motTextSetLinColToPosition(str, lin_start, col_start); + end = motTextSetLinColToPosition(str, lin_end, col_end); + XtFree(str); + } + else + { + if (iupStrToIntInt(value, &start, &end, ':')!=2) + return 0; + + if(start<1 || end<1) + return 0; + + start--; /* IUP starts at 1 */ + end--; + } + + /* end is inside the selection, in IUP is outside */ + end--; + + XmTextSetSelection(ih->handle, (XmTextPosition)start, (XmTextPosition)end, CurrentTime); + + return 0; +} + +static char* motTextGetSelectionAttrib(Ihandle* ih) +{ + XmTextPosition start = 0, end = 0; + char* str; + + if (!XmTextGetSelectionPosition(ih->handle, &start, &end) || start==end) + return NULL; + + str = iupStrGetMemory(100); + + /* end is inside the selection, in IUP is outside */ + end++; + + if (ih->data->is_multiline) + { + int start_col, start_lin, end_col, end_lin; + + char *value = XmTextGetString(ih->handle); + motTextGetLinColFromPosition(value, start, &start_lin, &start_col); + motTextGetLinColFromPosition(value, end, &end_lin, &end_col); + XtFree(value); + + sprintf(str,"%d,%d:%d,%d", start_lin, start_col, end_lin, end_col); + } + else + { + start++; /* IUP starts at 1 */ + end++; + sprintf(str, "%d:%d", (int)start, (int)end); + } + + return str; +} + +static int motTextSetSelectionPosAttrib(Ihandle* ih, const char* value) +{ + int start=0, end=0; + + if (!value || iupStrEqualNoCase(value, "NONE")) + { + XmTextClearSelection(ih->handle, CurrentTime); + return 0; + } + + if (iupStrEqualNoCase(value, "ALL")) + { + XmTextSetSelection(ih->handle, (XmTextPosition)0, (XmTextPosition)XmTextGetLastPosition(ih->handle), CurrentTime); + return 0; + } + + if (iupStrToIntInt(value, &start, &end, ':')!=2) + return 0; + + if(start<0 || end<0) + return 0; + + /* end is inside the selection, in IUP is outside */ + end--; + + XmTextSetSelection(ih->handle, (XmTextPosition)start, (XmTextPosition)end, CurrentTime); + + return 0; +} + +static char* motTextGetSelectionPosAttrib(Ihandle* ih) +{ + XmTextPosition start = 0, end = 0; + char* str; + + if (!XmTextGetSelectionPosition(ih->handle, &start, &end) || start==end) + return NULL; + + str = iupStrGetMemory(100); + + /* end is inside the selection, in IUP is outside */ + end++; + + sprintf(str, "%d:%d", (int)start, (int)end); + + return str; +} + +static int motTextSetCaretAttrib(Ihandle* ih, const char* value) +{ + int pos = 1; + + if (!value) + return 0; + + if (ih->data->is_multiline) + { + int lin = 1, col = 1; + char *str; + + iupStrToIntInt(value, &lin, &col, ','); + + str = XmTextGetString(ih->handle); + pos = motTextSetLinColToPosition(str, lin, col); + XtFree(str); + } + else + { + sscanf(value,"%i",&pos); + pos--; /* IUP starts at 1 */ + } + + XmTextSetInsertionPosition(ih->handle, (XmTextPosition)pos); + XmTextShowPosition(ih->handle, (XmTextPosition)pos); + + return 0; +} + +static char* motTextGetCaretAttrib(Ihandle* ih) +{ + char* str = iupStrGetMemory(50); + + XmTextPosition pos = XmTextGetInsertionPosition(ih->handle); + + if (ih->data->is_multiline) + { + int col, lin; + + char *value = XmTextGetString(ih->handle); + motTextGetLinColFromPosition(value, pos, &lin, &col); + XtFree(value); + + sprintf(str, "%d,%d", lin, col); + } + else + { + pos++; /* IUP starts at 1 */ + sprintf(str, "%d", (int)pos); + } + + return str; +} + +static int motTextSetCaretPosAttrib(Ihandle* ih, const char* value) +{ + int pos = 0; + + if (!value) + return 0; + + sscanf(value,"%i",&pos); + if (pos < 0) pos = 0; + + XmTextSetInsertionPosition(ih->handle, (XmTextPosition)pos); + XmTextShowPosition(ih->handle, (XmTextPosition)pos); + + return 0; +} + +static char* motTextGetCaretPosAttrib(Ihandle* ih) +{ + XmTextPosition pos = XmTextGetInsertionPosition(ih->handle); + char* str = iupStrGetMemory(50); + sprintf(str, "%d", (int)pos); + return str; +} + +static int motTextSetScrollToAttrib(Ihandle* ih, const char* value) +{ + int pos = 1; + + if (!value) + return 0; + + if (ih->data->is_multiline) + { + int lin = 1, col = 1, pos; + char* str; + + iupStrToIntInt(value, &lin, &col, ','); + if (lin < 1) lin = 1; + if (col < 1) col = 1; + + str = XmTextGetString(ih->handle); + pos = motTextSetLinColToPosition(str, lin, col); + XtFree(str); + } + else + { + sscanf(value,"%i",&pos); + if (pos < 1) pos = 1; + pos--; /* return to Motif referece */ + } + + XmTextShowPosition(ih->handle, (XmTextPosition)pos); + + return 0; +} + +static int motTextSetScrollToPosAttrib(Ihandle* ih, const char* value) +{ + int pos = 0; + + if (!value) + return 0; + + sscanf(value,"%i",&pos); + if (pos < 0) pos = 0; + + XmTextShowPosition(ih->handle, (XmTextPosition)pos); + + return 0; +} + +static int motTextSetNCAttrib(Ihandle* ih, const char* value) +{ + if (!iupStrToInt(value, &ih->data->nc)) + ih->data->nc = INT_MAX; + if (ih->handle) + XtVaSetValues(ih->handle, XmNmaxLength, ih->data->nc, NULL); + return 0; +} + +static int motTextSetClipboardAttrib(Ihandle *ih, const char *value) +{ + if (iupStrEqualNoCase(value, "COPY")) + { + char *str = XmTextGetSelection(ih->handle); + if (!str) return 0; + + XmTextCopy(ih->handle, CurrentTime); + + /* do it also for the X clipboard */ + XStoreBytes(iupmot_display, str, strlen(str)+1); + XtFree(str); + } + else if (iupStrEqualNoCase(value, "CUT")) + { + char *str = XmTextGetSelection(ih->handle); + if (!str) return 0; + + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + + XmTextCut(ih->handle, CurrentTime); + + /* do it also for the X clipboard */ + XStoreBytes(iupmot_display, str, strlen(str)+1); + XtFree(str); + XmTextRemove(ih->handle); + + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + else if (iupStrEqualNoCase(value, "PASTE")) + { + int size; + char* str = XFetchBytes(iupmot_display, &size); + if (!str) return 0; + + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + + XmTextPaste(ih->handle); /* TODO: this could force 2 pastes, check in CDE */ + + /* do it also for the X clipboard */ + XmTextRemove(ih->handle); + XmTextInsert(ih->handle, XmTextGetInsertionPosition(ih->handle), str); + XFree(str); + + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + else if (iupStrEqualNoCase(value, "CLEAR")) + { + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XmTextRemove(ih->handle); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + return 0; +} + +static int motTextSetBgColorAttrib(Ihandle* ih, const char* value) +{ + Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (sb_win) + { + Pixel color; + + /* ignore given value for the scrollbars, must use only from parent */ + char* parent_value = iupBaseNativeParentGetBgColor(ih); + + color = iupmotColorGetPixelStr(parent_value); + if (color != (Pixel)-1) + { + Widget sb = NULL; + + iupmotSetBgColor(sb_win, color); + + XtVaGetValues(sb_win, XmNverticalScrollBar, &sb, NULL); + if (sb) iupmotSetBgColor(sb, color); + + XtVaGetValues(sb_win, XmNhorizontalScrollBar, &sb, NULL); + if (sb) iupmotSetBgColor(sb, color); + } + } + + return iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */ +} + +static int motTextSetSpinMinAttrib(Ihandle* ih, const char* value) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + int min; + if (iupStrToInt(value, &min)) + { + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XtVaSetValues(ih->handle, XmNminimumValue, min, NULL); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + } + return 1; +} + +static int motTextSetSpinMaxAttrib(Ihandle* ih, const char* value) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + int max; + if (iupStrToInt(value, &max)) + { + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XtVaSetValues(ih->handle, XmNmaximumValue, max, NULL); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + } + return 1; +} + +static int motTextSetSpinIncAttrib(Ihandle* ih, const char* value) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + int inc; + if (iupStrToInt(value, &inc)) + { + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XtVaSetValues(ih->handle, XmNincrementValue, inc, NULL); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + } + } + return 1; +} + +static int motTextSetSpinValueAttrib(Ihandle* ih, const char* value) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + int pos; + if (iupStrToInt(value, &pos)) + { + char* value = NULL; + int min, max; + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XtVaGetValues(ih->handle, XmNminimumValue, &min, + XmNmaximumValue, &max, NULL); + if (pos < min) pos = min; + if (pos > max) pos = max; + if (iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO")) + value = XmTextGetString(ih->handle); + + XtVaSetValues(ih->handle, XmNposition, pos, NULL); + + if (value) + { + XmTextSetString(ih->handle, (char*)value); + XtFree(value); + } + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + return 1; + } + } + return 0; +} + +static char* motTextGetSpinValueAttrib(Ihandle* ih) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + int pos; + char *str = iupStrGetMemory(50); + XtVaGetValues(ih->handle, XmNposition, &pos, NULL); + sprintf(str, "%d", pos); + return str; + } + return NULL; +} + +static int motTextSetValueAttrib(Ihandle* ih, const char* value) +{ + if (!value) value = ""; + motTextSetSpinValueAttrib(ih, value); + /* disable callbacks */ + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XmTextSetString(ih->handle, (char*)value); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + return 0; +} + +static char* motTextGetValueAttrib(Ihandle* ih) +{ + char* value = XmTextGetString(ih->handle); + char* str = iupStrGetMemoryCopy(value); + XtFree(value); + return str; +} + + +/******************************************************************************/ + + +static void motTextSpinModifyVerifyCallback(Widget w, Ihandle* ih, XmSpinBoxCallbackStruct *cbs) +{ + IFni cb = (IFni) IupGetCallback(ih, "SPIN_CB"); + if (cb) + { + int ret = cb(ih, cbs->position); + if (ret == IUP_IGNORE) + { + cbs->doit = 1; + return; + } + } + (void)w; + + iupAttribSetStr(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB", "1"); +} + +static void motTextModifyVerifyCallback(Widget w, Ihandle *ih, XmTextVerifyPtr text) +{ + int start, end, key = 0; + char *value, *new_value, *insert_value; + KeySym motcode = 0; + IFnis cb; + + if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB")) + return; + + if (iupAttribGet(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB")) + { + if (iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO")) + text->doit = False; + + iupAttribSetStr(ih, "_IUPMOT_SPIN_DISABLE_TEXT_CB", NULL); + return; + } + + cb = (IFnis)IupGetCallback(ih, "ACTION"); + if (!cb && !ih->data->mask) + return; + + if (text->event && text->event->type == KeyPress) + { + unsigned int state = ((XKeyEvent*)text->event)->state; + if (state & ControlMask || /* Ctrl */ + state & Mod1Mask || + state & Mod5Mask || /* Alt */ + state & Mod4Mask) /* Apple/Win */ + return; + + motcode = XKeycodeToKeysym(iupmot_display, ((XKeyEvent*)text->event)->keycode, 0); + } + + value = XmTextGetString(ih->handle); + start = text->startPos; + end = text->endPos; + insert_value = text->text->ptr; + + if (motcode == XK_Delete) + { + new_value = value; + iupStrRemove(value, start, end, 1); + } + else if (motcode == XK_BackSpace) + { + new_value = value; + iupStrRemove(value, start, end, -1); + } + else + { + if (!value) + new_value = iupStrDup(insert_value); + else if (insert_value) + new_value = iupStrInsert(value, insert_value, start, end); + else + new_value = value; + } + + if (insert_value && insert_value[0]!=0 && insert_value[1]==0) + key = insert_value[0]; + + if (ih->data->mask && iupMaskCheck(ih->data->mask, new_value)==0) + { + if (new_value != value) free(new_value); + XtFree(value); + text->doit = False; /* abort processing */ + return; + } + + if (cb) + { + int cb_ret = cb(ih, key, (char*)new_value); + if (cb_ret==IUP_IGNORE) + text->doit = False; /* abort processing */ + else if (cb_ret==IUP_CLOSE) + { + IupExitLoop(); + text->doit = False; /* abort processing */ + } + else if (cb_ret!=0 && key!=0 && + cb_ret != IUP_DEFAULT && cb_ret != IUP_CONTINUE) + { + insert_value[0] = (char)cb_ret; /* replace key */ + } + } + + if (text->doit) + { + /* Spin is not automatically updated when you directly edit the text */ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox) && !iupAttribGet(ih, "_IUPMOT_SPIN_NOAUTO")) + { + int pos; + if (iupStrToInt(new_value, &pos)) + { + XmTextPosition caret_pos = text->currInsert; + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1"); + XtVaSetValues(ih->handle, XmNposition, pos, NULL); + iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", NULL); + /* do not handle all situations, but handle the basic ones */ + if (text->startPos == text->endPos) /* insert */ + caret_pos++; + else if (text->startPos < text->endPos && text->startPos < text->currInsert) /* backspace */ + caret_pos--; + XmTextSetInsertionPosition(ih->handle, caret_pos); + text->doit = False; + } + } + } + + if (new_value != value) free(new_value); + XtFree(value); + (void)w; +} + +static void motTextMotionVerifyCallback(Widget w, Ihandle* ih, XmTextVerifyCallbackStruct* textverify) +{ + int col, lin, pos; + + IFniii cb = (IFniii)IupGetCallback(ih, "CARET_CB"); + if (!cb) return; + + pos = textverify->newInsert; + + if (ih->data->is_multiline) + { + char *value = XmTextGetString(ih->handle); + motTextGetLinColFromPosition(value, pos, &lin, &col); + XtFree(value); + } + else + { + col = pos; + col++; /* IUP starts at 1 */ + lin = 1; + } + + if (pos != ih->data->last_caret_pos) + { + ih->data->last_caret_pos = pos; + cb(ih, lin, col, pos); + } + + (void)w; +} + +static void motTextValueChangedCallback(Widget w, Ihandle* ih, XmAnyCallbackStruct* valuechanged) +{ + if (iupAttribGet(ih, "_IUPMOT_DISABLE_TEXT_CB")) + return; + + iupBaseCallValueChangedCb(ih); + + (void)valuechanged; + (void)w; +} + +static void motTextKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean *cont) +{ + Widget spinbox; + + *cont = True; + iupmotKeyPressEvent(w, ih, (XEvent*)evt, cont); + if (*cont == False) + return; + + if (evt->state & ControlMask) /* Ctrl */ + { + KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0); + if (motcode == XK_c) + motTextSetClipboardAttrib(ih, "COPY"); + else if (motcode == XK_x) + motTextSetClipboardAttrib(ih, "CUT"); + else if (motcode == XK_v) + motTextSetClipboardAttrib(ih, "PASTE"); + else if (motcode == XK_a) + XmTextSetSelection(ih->handle, 0, XmTextGetLastPosition(ih->handle), CurrentTime); + } + + spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + KeySym motcode = XKeycodeToKeysym(iupmot_display, evt->keycode, 0); + if (motcode == XK_Left || motcode == XK_Right) + { + /* avoid spin increment using Left/Right arrows, + but must manually handle the new cursor position */ + XmTextPosition caret_pos = XmTextGetInsertionPosition(ih->handle); + XmTextSetInsertionPosition(ih->handle, (motcode == XK_Left)? caret_pos-1: caret_pos+1); + *cont = False; + } + } +} + + +/******************************************************************************/ + + +static void motTextLayoutUpdateMethod(Ihandle* ih) +{ + Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT"); + if (spinbox && XmIsSpinBox(spinbox)) + { + XtVaSetValues(ih->handle, + XmNwidth, (XtArgVal)ih->currentwidth-ih->currentheight/2, + XmNheight, (XtArgVal)ih->currentheight, + NULL); + + XtVaSetValues(spinbox, + XmNx, (XtArgVal)ih->x, + XmNy, (XtArgVal)ih->y, + XmNwidth, (XtArgVal)ih->currentwidth, + XmNheight, (XtArgVal)ih->currentheight, + XmNarrowSize, ih->currentheight/2, + NULL); + } + else + iupdrvBaseLayoutUpdateMethod(ih); +} + +static int motTextMapMethod(Ihandle* ih) +{ + int num_args = 0; + Arg args[30]; + Widget parent = iupChildTreeGetNativeParentHandle(ih); + char* child_id = iupDialogGetChildIdStr(ih); + int spin = 0; + WidgetClass widget_class = xmTextWidgetClass; + + if (ih->data->is_multiline) + { + Widget sb_win; + int wordwrap = 0; + + if (iupAttribGetBoolean(ih, "WORDWRAP")) + { + wordwrap = 1; + ih->data->sb &= ~IUP_SB_HORIZ; /* must remove the horizontal scroolbar */ + } + + /******************************/ + /* Create the scrolled window */ + /******************************/ + + iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */ + iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED); + iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE); + iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */ + iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */ + iupmotSetArg(args, num_args, XmNborderWidth, 0); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + + sb_win = XtCreateManagedWidget( + child_id, /* child identifier */ + xmScrolledWindowWidgetClass, /* widget class */ + parent, /* widget parent */ + args, num_args); + + if (!sb_win) + return IUP_ERROR; + + parent = sb_win; + child_id = "text"; + + num_args = 0; + iupmotSetArg(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT); + if (wordwrap) + iupmotSetArg(args, num_args, XmNwordWrap, True); + } + else + { + widget_class = xmTextFieldWidgetClass; + + if (iupAttribGetBoolean(ih, "SPIN")) + { + Widget spinbox; + + num_args = 0; + iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */ + iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between spin and text */ + iupmotSetArg(args, num_args, XmNborderWidth, 0); + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + iupmotSetArg(args, num_args, XmNmarginHeight, 0); + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + iupmotSetArg(args, num_args, XmNarrowSize, 8); + + if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT")) + iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING); + else + iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_END); + + spinbox = XtCreateManagedWidget( + child_id, /* child identifier */ + xmSpinBoxWidgetClass, /* widget class */ + parent, /* widget parent */ + args, num_args); + + if (!spinbox) + return IUP_ERROR; + + XtAddCallback(spinbox, XmNmodifyVerifyCallback, (XtCallbackProc)motTextSpinModifyVerifyCallback, (XtPointer)ih); + + parent = spinbox; + child_id = "text"; + spin = 1; + + if (!iupAttribGetBoolean(ih, "SPINAUTO")) + iupAttribSetStr(ih, "_IUPMOT_SPIN_NOAUTO", "1"); + } + + num_args = 0; + iupmotSetArg(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT); + + if (spin) + { + /* Spin Constraints */ + iupmotSetArg(args, num_args, XmNspinBoxChildType, XmNUMERIC); + iupmotSetArg(args, num_args, XmNminimumValue, 0); + iupmotSetArg(args, num_args, XmNmaximumValue, 100); + iupmotSetArg(args, num_args, XmNposition, 0); + + if (iupAttribGetBoolean(ih, "SPINWRAP")) + iupmotSetArg(args, num_args, XmNwrap, TRUE); + else + iupmotSetArg(args, num_args, XmNwrap, FALSE); + } + else + { + iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */ + } + } + + iupmotSetArg(args, num_args, XmNx, 0); /* x-position */ + iupmotSetArg(args, num_args, XmNy, 0); /* y-position */ + iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */ + iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */ + + iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */ + iupmotSetArg(args, num_args, XmNmarginWidth, 0); + + if (iupAttribGetBoolean(ih, "CANFOCUS")) + iupmotSetArg(args, num_args, XmNtraversalOn, True); + else + iupmotSetArg(args, num_args, XmNtraversalOn, False); + + iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); + iupmotSetArg(args, num_args, XmNhighlightThickness, 2); + iupmotSetArg(args, num_args, XmNverifyBell, False); + iupmotSetArg(args, num_args, XmNspacing, 0); + + if (iupAttribGetBoolean(ih, "BORDER")) + iupmotSetArg(args, num_args, XmNshadowThickness, 2); + else + iupmotSetArg(args, num_args, XmNshadowThickness, 0); + + if (ih->data->is_multiline) + { + if (ih->data->sb & IUP_SB_HORIZ) + iupmotSetArg(args, num_args, XmNscrollHorizontal, True); + else + iupmotSetArg(args, num_args, XmNscrollHorizontal, False); + + if (ih->data->sb & IUP_SB_VERT) + iupmotSetArg(args, num_args, XmNscrollVertical, True); + else + iupmotSetArg(args, num_args, XmNscrollVertical, False); + } + + ih->handle = XtCreateManagedWidget( + child_id, /* child identifier */ + widget_class, /* widget class */ + parent, /* widget parent */ + args, num_args); + + if (!ih->handle) + return IUP_ERROR; + + ih->serial = iupDialogGetChildId(ih); /* must be after using the string */ + + if (ih->data->is_multiline) + { + iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent); + XtVaSetValues(parent, XmNworkWindow, ih->handle, NULL); + } + else if (spin) + iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)parent); + + XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih); + XtAddEventHandler(ih->handle, EnterWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, LeaveWindowMask, False, (XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, FocusChangeMask, False, (XtEventHandler)iupmotFocusChangeEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, KeyPressMask, False, (XtEventHandler)motTextKeyPressEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih); + XtAddEventHandler(ih->handle, ButtonPressMask|ButtonReleaseMask, False, (XtEventHandler)iupmotButtonPressReleaseEvent, (XtPointer)ih); + + XtAddCallback(ih->handle, XmNmodifyVerifyCallback, (XtCallbackProc)motTextModifyVerifyCallback, (XtPointer)ih); + XtAddCallback(ih->handle, XmNmotionVerifyCallback, (XtCallbackProc)motTextMotionVerifyCallback, (XtPointer)ih); + XtAddCallback(ih->handle, XmNvalueChangedCallback, (XtCallbackProc)motTextValueChangedCallback, (XtPointer)ih); + + /* Disable Drag Source */ + iupmotDisableDragSource(ih->handle); + + /* initialize the widget */ + if (ih->data->is_multiline || spin) + XtRealizeWidget(parent); + else + XtRealizeWidget(ih->handle); + + if (IupGetGlobal("_IUP_RESET_TXTCOLORS")) + { + iupmotSetGlobalColorAttrib(ih->handle, XmNbackground, "TXTBGCOLOR"); + iupmotSetGlobalColorAttrib(ih->handle, XmNforeground, "TXTFGCOLOR"); + IupSetGlobal("_IUP_RESET_TXTCOLORS", NULL); + } + + IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTextConvertXYToPos); + + return IUP_NOERROR; +} + +void iupdrvTextInitClass(Iclass* ic) +{ + /* Driver Dependent Class functions */ + ic->Map = motTextMapMethod; + ic->LayoutUpdate = motTextLayoutUpdateMethod; + + /* Driver Dependent Attribute functions */ + + /* Overwrite Visual */ + iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT); + + /* Special */ + iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iupdrvBaseSetFgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_DEFAULT); + + /* IupText only */ + iupClassRegisterAttribute(ic, "PADDING", iupTextGetPaddingAttrib, motTextSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED); + iupClassRegisterAttribute(ic, "VALUE", motTextGetValueAttrib, motTextSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SELECTEDTEXT", motTextGetSelectedTextAttrib, motTextSetSelectedTextAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SELECTION", motTextGetSelectionAttrib, motTextSetSelectionAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SELECTIONPOS", motTextGetSelectionPosAttrib, motTextSetSelectionPosAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "CARET", motTextGetCaretAttrib, motTextSetCaretAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "CARETPOS", motTextGetCaretPosAttrib, motTextSetCaretPosAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "INSERT", NULL, motTextSetInsertAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "APPEND", NULL, motTextSetAppendAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "READONLY", motTextGetReadOnlyAttrib, motTextSetReadOnlyAttrib, NULL, NULL, IUPAF_DEFAULT); + iupClassRegisterAttribute(ic, "NC", iupTextGetNCAttrib, motTextSetNCAttrib, NULL, NULL, IUPAF_NOT_MAPPED); + iupClassRegisterAttribute(ic, "CLIPBOARD", NULL, motTextSetClipboardAttrib, NULL, NULL, IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "FORMATTING", NULL, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* formatting not supported in Motif */ + iupClassRegisterAttribute(ic, "SCROLLTO", NULL, motTextSetScrollToAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SCROLLTOPOS", NULL, motTextSetScrollToPosAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SPINMIN", NULL, motTextSetSpinMinAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SPINMAX", NULL, motTextSetSpinMaxAttrib, IUPAF_SAMEASSYSTEM, "100", IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SPININC", NULL, motTextSetSpinIncAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NO_INHERIT); + iupClassRegisterAttribute(ic, "SPINVALUE", motTextGetSpinValueAttrib, motTextSetSpinValueAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NO_INHERIT); +} |