/* $XConsortium: TextFunc.c /main/16 1996/11/19 12:37:29 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. * */ /* * (c) Copyright 1995 FUJITSU LIMITED * This is source code modified by FUJITSU LIMITED under the Joint * Development Agreement for the CDEnext PST. * This is unpublished proprietary source code of FUJITSU LIMITED */ #include #include #include "XmI.h" #include "TextFI.h" #include "TextI.h" #include "TextInI.h" #include "TextStrSoI.h" /**************************************************************** * * Public definitions with TextField calls. * ****************************************************************/ XmTextPosition XmTextGetLastPosition(Widget widget) { XmTextPosition ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)){ XmTextFieldWidget tf = (XmTextFieldWidget) widget; ret_val = tf->text.string_length; } else { XmTextSource source; source = GetSrc(widget); ret_val = (*source->Scan)(source, 0, XmSELECT_ALL, XmsdRight, 1, TRUE); } _XmAppUnlock(app); return ret_val; } void _XmTextReplace(Widget widget, XmTextPosition frompos, XmTextPosition topos, char *value, #if NeedWidePrototypes int is_wchar) #else Boolean is_wchar) #endif /* NeedWidePrototypes */ { XmTextWidget tw = (XmTextWidget) widget; XmTextSource source; XmTextBlockRec block, newblock; Boolean editable, freeBlock; Boolean need_free = False; int max_length; int num_chars; wchar_t * tmp_wc; XmTextPosition selleft, selright, cursorPos; char * tmp_block = NULL; source = GetSrc(tw); (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off); if ((*source->GetSelection)(tw->text.source, &selleft, &selright)) { if ((selleft > frompos && selleft < topos) || (selright >frompos && selright < topos) || (selleft <= frompos && selright >= topos)) { (*source->SetSelection)(tw->text.source, tw->text.cursor_position, tw->text.cursor_position, XtLastTimestampProcessed(XtDisplay(widget))); if (tw->text.input->data->pendingdelete) tw->text.pendingoff = FALSE; } } block.format = XmFMT_8_BIT; if (!is_wchar) { if (value == NULL) block.length = 0; else block.length = strlen(value); block.ptr = value; } else { /* value is really a wchar_t ptr cast to char* */ if (value == NULL) { block.length = 0; } else { for (tmp_wc = (wchar_t*)value, num_chars = 0; *tmp_wc != (wchar_t)0L; num_chars++) tmp_wc++; tmp_block = XtMalloc((unsigned) (num_chars + 1) * (int)tw->text.char_size); block.ptr = tmp_block; need_free = True; tmp_wc = (wchar_t *) value; /* if successful, wcstombs returns number of bytes, else -1 */ block.length = wcstombs(block.ptr, tmp_wc, (num_chars + 1) * (int)tw->text.char_size); if (block.length == -1) { block.length = 0; /* if error, don't insert anything */ block.ptr[0] = '\0'; /* use the empty string */ } } } editable = _XmStringSourceGetEditable(source); max_length = _XmStringSourceGetMaxLength(source); _XmStringSourceSetEditable(source, TRUE); _XmStringSourceSetMaxLength(source, INT_MAX); if (_XmTextModifyVerify(tw, NULL, &frompos, &topos, &cursorPos, &block, &newblock, &freeBlock)) { (*source->Replace)(tw, NULL, &frompos, &topos, &newblock, False); if (frompos == tw->text.cursor_position && frompos == topos) { _XmTextSetCursorPosition((Widget)tw, cursorPos); } _XmTextValueChanged(tw, NULL); if (UnderVerifyPreedit(tw)) if (newblock.length != block.length || strncmp(newblock.ptr, block.ptr, block.length) != 0) { VerifyCommitNeeded(tw) = True; PreEndTW(tw) += _XmTextCountCharacters(newblock.ptr, newblock.length) - _XmTextCountCharacters(block.ptr, block.length); } if (freeBlock && newblock.ptr) XtFree(newblock.ptr); } else if (UnderVerifyPreedit(tw)) { VerifyCommitNeeded(tw) = True; PreEndTW(tw) -= _XmTextCountCharacters(block.ptr, block.length); } if (need_free) XtFree(tmp_block); _XmStringSourceSetEditable(source, editable); _XmStringSourceSetMaxLength(source, max_length); if (tw->text.input->data->has_destination) _XmTextSetDestinationSelection(widget, tw->text.cursor_position, False, XtLastTimestampProcessed(XtDisplay(widget))); (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on); } void XmTextReplace(Widget widget, XmTextPosition frompos, XmTextPosition topos, char *value) { if (XmIsTextField(widget)) XmTextFieldReplace(widget, frompos, topos, value); else { _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextReplace(widget, frompos, topos, value, False); _XmAppUnlock(app); } } void XmTextReplaceWcs(Widget widget, XmTextPosition frompos, XmTextPosition topos, wchar_t *value) { if (XmIsTextField(widget)) XmTextFieldReplaceWcs(widget, frompos, topos, (wchar_t*) value); else { _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextReplace(widget, frompos, topos, (char*) value, True); _XmAppUnlock(app); } } void XmTextInsert(Widget widget, XmTextPosition position, char *value) { XmTextReplace(widget, position, position, value); } void XmTextInsertWcs(Widget widget, XmTextPosition position, wchar_t *wc_value) { XmTextReplaceWcs(widget, position, position, wc_value); } void XmTextSetAddMode(Widget widget, #if NeedWidePrototypes int state) #else Boolean state) #endif /* NeedWidePrototypes */ { if (XmIsTextField(widget)) XmTextFieldSetAddMode(widget, state); else { XmTextWidget tw = (XmTextWidget) widget; _XmWidgetToAppContext(widget); _XmAppLock(app); if (tw->text.add_mode == state) { _XmAppUnlock(app); return; } (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off); tw->text.add_mode = state; (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on); _XmAppUnlock(app); } } Boolean XmTextGetAddMode(Widget widget) { Boolean ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)){ XmTextFieldWidget tf = (XmTextFieldWidget) widget; ret_val = tf->text.add_mode; } else { XmTextWidget tw = (XmTextWidget) widget; ret_val = tw->text.add_mode; } _XmAppUnlock(app); return ret_val; } Boolean XmTextGetEditable(Widget widget) { Boolean ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) ret_val = TextF_Editable(widget); else ret_val = _XmStringSourceGetEditable(GetSrc(widget)); _XmAppUnlock(app); return ret_val; } void XmTextSetEditable(Widget widget, #if NeedWidePrototypes int editable) #else Boolean editable) #endif /* NeedWidePrototypes */ { if (XmIsTextField(widget)) XmTextFieldSetEditable(widget, editable); else { _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextSetEditable(widget, editable); _XmAppUnlock(app); } } int XmTextGetMaxLength(Widget widget) { int ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) ret_val = TextF_MaxLength(widget); else ret_val = _XmStringSourceGetMaxLength(GetSrc(widget)); _XmAppUnlock(app); return ret_val; } void XmTextSetMaxLength(Widget widget, int max_length) { _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) TextF_MaxLength(widget) = max_length; else { XmTextWidget tw = (XmTextWidget) widget; tw->text.max_length = max_length; _XmStringSourceSetMaxLength(GetSrc(tw), max_length); } _XmAppUnlock(app); } XmTextPosition XmTextGetInsertionPosition(Widget widget) { XmTextPosition ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) ret_val = TextF_CursorPosition(widget); else { XmTextWidget tw = (XmTextWidget) widget; ret_val = tw->text.cursor_position; } _XmAppUnlock(app); return ret_val; } void XmTextSetInsertionPosition(Widget widget, XmTextPosition position) { XmTextWidget tw = (XmTextWidget) widget; if (XmIsTextField(widget)) XmTextFieldSetInsertionPosition(widget, position); else { _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextResetIC(widget); _XmTextSetCursorPosition(widget, position); _XmTextSetDestinationSelection(widget, tw->text.cursor_position, False, XtLastTimestampProcessed(XtDisplay(widget))); _XmAppUnlock(app); } } Boolean XmTextRemove(Widget widget) { if (XmIsTextField(widget)) return(XmTextFieldRemove(widget)); else { XmTextWidget tw = (XmTextWidget) widget; XmTextSource source; XmTextPosition left, right; _XmWidgetToAppContext(widget); _XmAppLock(app); if (tw->text.editable == False) { _XmAppUnlock(app); return False; } source = tw->text.source; _XmTextResetIC(widget); if (!(*source->GetSelection)(source, &left, &right) || left == right) { tw->text.input->data->anchor = tw->text.cursor_position; _XmAppUnlock(app); return False; } XmTextReplace(widget, left, right, NULL); if (tw->text.cursor_position > left) _XmTextSetCursorPosition(widget, left); tw->text.input->data->anchor = tw->text.cursor_position; _XmAppUnlock(app); return True; } } Boolean XmTextCopy(Widget widget, Time copy_time) { Boolean result = False; XmTextPosition left, right; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmTextGetSelectionPosition(widget, &left, &right) && right != left) /* start copy to clipboard */ result = XmeClipboardSource(widget, XmCOPY, copy_time); _XmAppUnlock(app); return result; } Boolean XmTextCopyLink(Widget widget, Time copy_time) { Boolean result = False; XmTextPosition left, right; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmTextGetSelectionPosition(widget, &left, &right) && right != left) /* start copy to clipboard */ result = XmeClipboardSource(widget, XmLINK, copy_time); _XmAppUnlock(app); return result; } Boolean XmTextCut(Widget widget, Time cut_time) { Boolean result = False; XmTextPosition left, right; _XmWidgetToAppContext(widget); _XmAppLock(app); /* can't cut if you can't edit */ if (XmTextGetEditable(widget) && XmTextGetSelectionPosition(widget, &left, &right) && (right != left)) /* start copy to clipboard */ result = XmeClipboardSource(widget, XmMOVE, cut_time); _XmAppUnlock(app); return result; } /* * Retrieves the current data from the clipboard * and paste it at the current cursor position */ Boolean XmTextPaste(Widget widget) { Boolean status; InputData data; _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextResetIC(widget); data = ((XmTextWidget) widget)->text.input->data; data->selectionMove = FALSE; data->selectionLink = FALSE; status = XmeClipboardSink(widget, XmCOPY, NULL); _XmAppUnlock(app); return(status); } /* * Retrieves the current data from the clipboard * and paste it at the current cursor position */ Boolean XmTextPasteLink(Widget widget) { Boolean status; InputData data; _XmWidgetToAppContext(widget); _XmAppLock(app); data = ((XmTextWidget) widget)->text.input->data; data->selectionMove = FALSE; data->selectionLink = True; status = XmeClipboardSink(widget, XmLINK, NULL); _XmAppUnlock(app); return(status); } char * XmTextGetSelection(Widget widget) { if (XmIsTextField(widget)) return(XmTextFieldGetSelection(widget)); else { XmTextSource source; XmTextPosition left, right; char *ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); source = GetSrc(widget); if ((!(*source->GetSelection)(source, &left, &right)) || right == left) { _XmAppUnlock(app); return NULL; } ret_val = _XmStringSourceGetString((XmTextWidget)widget, left, right, False); _XmAppUnlock(app); return ret_val; } } wchar_t * XmTextGetSelectionWcs(Widget widget) { if (XmIsTextField(widget)) return(XmTextFieldGetSelectionWcs(widget)); else { XmTextSource source; XmTextPosition left, right; wchar_t *ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); source = GetSrc(widget); if (!(*source->GetSelection)(source, &left, &right)) { _XmAppUnlock(app); return NULL; } ret_val = (wchar_t *)_XmStringSourceGetString((XmTextWidget)widget, left, right, True); _XmAppUnlock(app); return ret_val; } } void XmTextSetSelection(Widget widget, XmTextPosition first, XmTextPosition last, Time set_time) { if (XmIsTextField(widget)) XmTextFieldSetSelection(widget, first, last, set_time); else { XmTextSource source; XmTextWidget tw = (XmTextWidget) widget; _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextResetIC(widget); if (first < 0 || last > tw->text.last_position) { _XmAppUnlock(app); return; } source = GetSrc(widget); source->data->take_selection = True; (*source->SetSelection)(source, first, last, set_time); tw->text.pendingoff = FALSE; _XmTextSetCursorPosition(widget, last); _XmTextSetDestinationSelection(widget, tw->text.cursor_position, False, set_time); _XmAppUnlock(app); } } void XmTextClearSelection(Widget widget, Time clear_time) { if (XmIsTextField(widget)) XmTextFieldClearSelection(widget, clear_time); else { XmTextWidget tw = (XmTextWidget) widget; XmTextSource source = GetSrc(widget); _XmWidgetToAppContext(widget); _XmAppLock(app); (*source->SetSelection)(source, 1, -999, source->data->prim_time); if (tw->text.input->data->pendingdelete) { tw->text.pendingoff = FALSE; } _XmAppUnlock(app); } } Boolean XmTextGetSelectionPosition(Widget widget, XmTextPosition *left, XmTextPosition *right) { Boolean ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) { XmTextFieldWidget tf = (XmTextFieldWidget) widget; if (!tf->text.has_primary) { ret_val = False; } else { *left = tf->text.prim_pos_left; *right = tf->text.prim_pos_right; ret_val = True; } } else { XmTextWidget tw = (XmTextWidget) widget; ret_val = (*tw->text.source->GetSelection)(tw->text.source, left, right); } _XmAppUnlock(app); return ret_val; } XmTextPosition XmTextXYToPos(Widget widget, #if NeedWidePrototypes int x, int y) #else Position x, Position y) #endif /* NeedWidePrototypes */ { if (XmIsTextField(widget)) return(XmTextFieldXYToPos(widget, x, y)); else { XmTextWidget tw = (XmTextWidget) widget; XmTextPosition ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); ret_val = (*tw->text.output->XYToPos)(tw, x, y); _XmAppUnlock(app); return ret_val; } } Boolean XmTextPosToXY(Widget widget, XmTextPosition position, Position *x, Position *y) { if (XmIsTextField(widget)) return(XmTextFieldPosToXY(widget, position, x, y)); else { XmTextWidget tw = (XmTextWidget) widget; Boolean ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); ret_val = (*tw->text.output->PosToXY)(tw, position, x, y); _XmAppUnlock(app); return ret_val; } } /* * Force the given position to be displayed. If position < 0, then don't force * any position to be displayed. */ /* ARGSUSED */ void XmTextShowPosition(Widget widget, XmTextPosition position) { if (XmIsTextField(widget)) XmTextFieldShowPosition(widget, position); else { _XmWidgetToAppContext(widget); _XmAppLock(app); _XmTextShowPosition(widget, position); _XmAppUnlock(app); } } int XmTextGetBaseline(Widget widget) { _XmWidgetToAppContext(widget); _XmAppLock(app); if (XmIsTextField(widget)) { XmTextFieldWidget tf = (XmTextFieldWidget) widget; Dimension margin_top; int ret_val; if(XmDirectionMatch(XmPrim_layout_direction(tf), XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) { _XmAppUnlock(app); return(0); } margin_top = tf->text.margin_top + tf->primitive.shadow_thickness + tf->primitive.highlight_thickness; ret_val = (int) margin_top + (int) TextF_FontAscent(tf); _XmAppUnlock(app); return ret_val; } else { Dimension *baselines; int temp_bl; int line_count; XmPrimitiveClassExt *wcePtr; XmTextWidget tw = (XmTextWidget) widget; if(XmDirectionMatch(XmPrim_layout_direction(tw), XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) { _XmAppUnlock(app); return(0); } wcePtr = _XmGetPrimitiveClassExtPtr(XtClass(widget), NULLQUARK); if (*wcePtr && (*wcePtr)->widget_baseline) (void) (*(*wcePtr)->widget_baseline)(widget, &baselines, &line_count); if (line_count) temp_bl = (int) baselines[0]; else temp_bl = 0; XtFree((char *) baselines); _XmAppUnlock(app); return (temp_bl); } } int XmTextGetCenterline(Widget widget) { Dimension *baselines; int temp_bl; int line_count; XmPrimitiveClassExt *wcePtr; XmTextWidget tw = (XmTextWidget) widget; _XmWidgetToAppContext(widget); _XmAppLock(app); if (!XmDirectionMatch(XmPrim_layout_direction(tw), XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) { _XmAppUnlock(app); return(0); } wcePtr = _XmGetPrimitiveClassExtPtr(XtClass(widget), NULLQUARK); if (*wcePtr && (*wcePtr)->widget_baseline) (void) (*(*wcePtr)->widget_baseline)(widget, &baselines, &line_count); if (line_count) temp_bl = (int) baselines[0]; else temp_bl = 0; XtFree((char *) baselines); _XmAppUnlock(app); return (temp_bl); } void XmTextSetHighlight(Widget w, XmTextPosition left, XmTextPosition right, XmHighlightMode mode) { if (XmIsTextField(w)) { XmTextFieldSetHighlight(w, left, right, mode); } else { _XmWidgetToAppContext(w); _XmAppLock(app); _XmTextSetHighlight(w, left, right, mode); _XmAppUnlock(app); } } static int _XmTextGetSubstring(Widget widget, XmTextPosition start, int num_chars, int buf_size, char *buffer, #if NeedWidePrototypes int want_wchar) #else Boolean want_wchar) #endif /* NeedWidePrototypes */ { XmTextWidget tw = (XmTextWidget) widget; XmTextBlockRec block; XmTextPosition pos, end; wchar_t * wc_buffer = (wchar_t*)buffer; int destpos = 0; end = start + num_chars; num_chars = 0; /* We're done with the value passed in, so let's * re-use it when needed for the wchar functionality * instead of creating a local automatic variable. */ for (pos = start; pos < end;) { pos = (*tw->text.source->ReadSource)(tw->text.source, pos, end, &block); if (block.length == 0) { if (!want_wchar) buffer[destpos] = '\0'; else wc_buffer[destpos] = (wchar_t)0L; return XmCOPY_TRUNCATED; } if (!want_wchar) { if (((destpos + block.length) * sizeof(char)) >= buf_size) return XmCOPY_FAILED; } else { /* Need number of characters for buffer comparison */ num_chars = _XmTextCountCharacters(block.ptr, block.length); if (((destpos + num_chars) * sizeof(char)) >= buf_size) return XmCOPY_FAILED; } if (!want_wchar) { (void)memcpy((void*)&buffer[destpos], (void*)block.ptr, block.length); destpos += block.length; } else { /* want wchar_t* data */ num_chars = mbstowcs(&wc_buffer[destpos], block.ptr, num_chars); if (num_chars < 0) num_chars = 0; destpos += num_chars; } } if (!want_wchar) buffer[destpos] = '\0'; else wc_buffer[destpos] = (wchar_t)0L; return XmCOPY_SUCCEEDED; } int XmTextGetSubstring(Widget widget, XmTextPosition start, int num_chars, int buf_size, char *buffer) { if (XmIsTextField(widget)) return (XmTextFieldGetSubstring(widget, start, num_chars, buf_size, buffer)); else { int ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); ret_val =_XmTextGetSubstring(widget, start, num_chars, buf_size, buffer, False); _XmAppUnlock(app); return ret_val; } } int XmTextGetSubstringWcs(Widget widget, XmTextPosition start, int num_chars, int buf_size, wchar_t *buffer) { if (XmIsTextField(widget)) return (XmTextFieldGetSubstringWcs(widget, start, num_chars, buf_size, buffer)); else { int ret_val; _XmWidgetToAppContext(widget); _XmAppLock(app); ret_val =_XmTextGetSubstring(widget, start, num_chars, buf_size, (char*) buffer, True); _XmAppUnlock(app); return ret_val; } }