/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company * * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. * * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994, 1996 Novell, Inc. * * (c) Copyright 1995, 1996 Digital Equipment Corporation. * * (c) Copyright 1996 FUJITSU LIMITED. * * (c) Copyright 1996 Hitachi. * */ #include "TermHeader.h" #include #include #include #include #include #include #include "TermPrimAction.h" #include "TermPrimDebug.h" #include "TermPrimP.h" #include "TermPrimData.h" #include "TermPrimRender.h" #include "TermPrimSelectP.h" #include "TermPrimBufferP.h" #include #include #include #include /* This is for Sun's two button mouse */ static char _DtTermEventBindingsCDE[] = "\ ~c ~s ~m ~a :process-press(grab-focus,process-bdrag)\n\ ~c s ~m ~a :process-press(extend-start,process-bdrag)\n\ ~c ~m ~a :select-adjust()\n\ ~c ~m ~a :extend-end()"; static char _DtTermEventBindingsCDEBtn2[] = "\ :extend-start()\n\ :select-adjust()\n\ :extend-end()"; static XmTextScanType defaultScanArray[] = { XmSELECT_POSITION, XmSELECT_WORD, XmSELECT_LINE, XmSELECT_ALL }; static void RegisterDropSite( Widget w ); static void doExtendedSelection (Widget w,Time eventTime); /* ** Get the current server time (I ripped this off from Xm/TextIn.c). */ static Time getServerTime ( Widget w ) { XEvent event; EventMask shellMask; while(!XtIsShell(w)) { w = XtParent(w); } shellMask = XtBuildEventMask(w); if (!(shellMask & PropertyChangeMask)) { XSelectInput(XtDisplay(w), XtWindow(w), shellMask | PropertyChangeMask); } XChangeProperty(XtDisplay(w), XtWindow(w), XA_WM_HINTS, XA_WM_HINTS, 32, PropModeAppend, (unsigned char *)NULL, 0); XWindowEvent(XtDisplay(w), XtWindow(w), PropertyChangeMask, &event); if (!(shellMask & PropertyChangeMask)) { XSelectInput(XtDisplay(w), XtWindow(w), shellMask); } return(event.xproperty.time); } static void setScanType ( Widget w, XEvent *event ) { TermSelectInfo selectInfo = ((DtTermPrimitiveWidget)w)->term.tpd->selectInfo; int multiClickTime; int i; multiClickTime = XtGetMultiClickTime(XtDisplay(w)); if (event->xbutton.time > selectInfo->lastTime && event->xbutton.time - selectInfo->lastTime < (multiClickTime == 200 ? 500 : multiClickTime)) { i = 0; while (i < selectInfo->scanArraySize && selectInfo->scanArray[i] != selectInfo->scanType) { i++; } if (++i >= selectInfo->scanArraySize) { i = 0; } selectInfo->scanType = selectInfo->scanArray[i]; } else { /* single-click event */ selectInfo->scanType = selectInfo->scanArray[0]; } selectInfo->lastTime = event->xbutton.time; } /* ** convert a row,col pair into the equivalent XmTextPosition ** ** NOTE: ** this routine assumes that the calling routine as already checked ** row and col to insure that they are within the bounds of the terminal ** buffer (see _DtTermPrimSelectGrabFocus) */ XmTextPosition rowColToPos ( DtTermPrimitiveWidget tw, short row, short col ) { DtTermPrimData tpd = tw->term.tpd; return(((tpd->selectInfo->columns + 1) * (row + tpd->lastUsedHistoryRow)) + col); } /* ** getSelection */ Boolean _DtTermPrimSelectGetSelection ( Widget w, XmTextPosition *begin, XmTextPosition *end ) { TermSelectInfo selectInfo = ((DtTermPrimitiveWidget)w)->term.tpd->selectInfo; if (selectInfo->ownPrimary && (selectInfo->begin <= selectInfo->end) && selectInfo->begin >= 0) { *begin = selectInfo->begin; *end = selectInfo->end; return(True); } else { *begin = 0; *end = 0; selectInfo->ownPrimary = False; return(False); } } /* ** convert an x,y pair into the appropriate text position ** ** Since positions count the number of inter-character spaces, there is ** one more x position on a line than columns on a line; xPos can be in ** the range (0, selectInfo->columns + 1). The same is true for yPos, ** it can be in the range (0, tpd->lastUsedRow - tpd->topRow - 1) ** ** In the case that we have a history buffer to deal with, text positions ** in the history buffer are forced to come before positions in the term ** buffer. ** ** NOTE: ** this routine assumes that the calling routine as already checked ** x and y to insure that they are within the bounds of the terminal ** window (see _DtTermPrimSelectGrabFocus) ** NOTE: ** I believe I'm now doing all checking in this routine for confining ** the x,y to the window. Disregard the previous note. TMH */ static XmTextPosition xyToPos ( DtTermPrimitiveWidget tw, int x, /* pixel */ int y /* pixel */ ) { DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; TermBuffer tb; short row; short yPos; short xPos; static short oldYPos = -1; static short oldXPos = -1; if ( x<0) x = 0; if ( x > (int) tw->core.width) x = tw->core.width; /* ** convert pixel units to character positions */ yPos = (MAX(0, y) - tpd->offsetY) / tpd->cellHeight; /* ** yPos cannot exceed the buffer or screen */ yPos = MIN(yPos, MIN(tw->term.rows, tpd->lastUsedRow - tpd->topRow) - 1) + tpd->topRow; /* ** consider the possibility that we have a history buffer */ if (tpd->useHistoryBuffer) { if (yPos < 0) { /* ** yPos is not in the history buffer (order is important, ** step 2 must come before step 3): ** 1) point to history buffer ** 2) adjust yPos ** 3) decide which row of the buffer we are concerned ** with */ tb = tpd->historyBuffer; yPos += tpd->lastUsedHistoryRow; row = yPos; } else { /* ** yPos is not in the history buffer (order is important, ** step 2 must come before step 3): ** 1) point to term buffer ** 2) decide which row of the buffer we are concerned ** with ** 3) adjust yPos */ tb = tpd->termBuffer; row = yPos; yPos += tpd->lastUsedHistoryRow; } } else { tb = tpd->termBuffer; row = yPos; } xPos = (((x - tpd->offsetX) + (tpd->cellWidth / 2)) / tpd->cellWidth) ; if ( MB_CUR_MAX > 1 ) /* check if xPos splits a 2 col char */ { TermCharInfoRec charInfoRec ; if (_DtTermPrimGetCharacterInfo(tb,row,xPos,&charInfoRec) ) { if (charInfoRec.width == 2 && charInfoRec.startCol != xPos) { if (xPos*tpd->cellWidth < x - tpd->offsetX ) xPos++ ; /* set to right of char */ else xPos-- ; /* set to left of char */ } } } if ((yPos != oldYPos) || (xPos != oldXPos)) { oldYPos = yPos; oldXPos = xPos; } return (((selectInfo->columns + 1) * yPos) + xPos); } /* * Takes a linear position and return buffer, row, and col. * Since positions are between characters, this returns the col to * right of the position. */ static void posToBufferRowCol ( DtTermPrimitiveWidget tw, XmTextPosition pos, TermBuffer *pb, short *row, short *col ) { DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; short lrow, lcol; lrow = pos / (selectInfo->columns + 1); lcol = pos - (lrow * (selectInfo->columns + 1)); if ( tpd->useHistoryBuffer ) lrow -= tpd->lastUsedHistoryRow ; if ( lrow < 0 ) { /* in history buffer */ *pb=tw->term.tpd->historyBuffer ; lrow += tpd->lastUsedHistoryRow ; } else { *pb = tpd->termBuffer ; } *row = lrow ; *col = lcol ; } /* * Takes a buffer, row and column and returns the linear position. */ static XmTextPosition bufferRowColToPos ( DtTermPrimitiveWidget tw, TermBuffer pb, short row, short col ) { DtTermPrimData tpd = tw->term.tpd; short lrow, lcol; XmTextPosition pos; /* assume row, col in the history buffer or there is no history */ pos = (tpd->selectInfo->columns + 1) * row + col; if ( tpd->useHistoryBuffer && pb == tpd->termBuffer) pos += (tpd->selectInfo->columns + 1) * (tpd->lastUsedHistoryRow) ; return(pos) ; } static XmTextPosition scan ( DtTermPrimitiveWidget tw, XmTextPosition scanStart, XmTextScanType scanType, TermScanDirection scanDir, int count, Boolean inclusive ) { int i; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; XmTextPosition position = scanStart; short row; short col; TermBuffer pb ; switch(scanType) { case XmSELECT_POSITION: posToBufferRowCol(tw, position, &pb, &row, &col) ; if ( col > _DtTermPrimBufferGetLineWidth(pb, row) ) { col = selectInfo->columns + 1; position = bufferRowColToPos(tw,pb,row,col) ; } break; case XmSELECT_WORD: { short width; posToBufferRowCol(tw, position, &pb, &row, &col) ; width = _DtTermPrimBufferGetLineWidth(pb,row); if ( col > width ) break; if ( MB_CUR_MAX > 1 ) { TermCharInfoRec charInfoRec ; _DtTermPrimGetCharacterInfo(pb,row,col,&charInfoRec); col = charInfoRec.startCol ; /* align first */ switch(scanDir) { case scanLeft: _DtTermPrimGetCharacterInfo(pb,row,col?--col:0,&charInfoRec); while( !iswspace(*(wchar_t *)charInfoRec.u.pwc) && ((col=charInfoRec.startCol-1)>=0) ) { _DtTermPrimGetCharacterInfo(pb,row,col,&charInfoRec) ; } col ++ ; break; case scanRight: _DtTermPrimGetCharacterInfo(pb,row,col,&charInfoRec); while(++col<=width && !iswspace(*(wchar_t *)charInfoRec.u.pwc)) _DtTermPrimGetCharacterInfo(pb,row,col,&charInfoRec); col--; break; } } else { char pbuf[10]; switch(scanDir) { case scanLeft: _DtTermPrimBufferGetText(pb, row, col?--col:0, 1, pbuf, False); while( !isspace(*pbuf) && --col >= 0) _DtTermPrimBufferGetText(pb, row, col, 1, pbuf, False ); col++ ; break; case scanRight: _DtTermPrimBufferGetText(pb, row, col, 1, pbuf, False); while( ++col <= width && !isspace(*pbuf)) _DtTermPrimBufferGetText(pb, row, col, 1, pbuf, False ); col--; break; } } position = bufferRowColToPos(tw,pb,row,col) ; } break; case XmSELECT_LINE: { posToBufferRowCol(tw, position, &pb, &row, &col) ; col = 0; switch(scanDir) { case scanLeft: break; case scanRight: col = selectInfo->columns + 1; break; } position = bufferRowColToPos(tw,pb,row,col) ; } break; case XmSELECT_ALL: switch(scanDir) { case scanLeft: position = 0; break; case scanRight: pb = tpd->termBuffer ; row = tpd->lastUsedRow-1; col = _DtTermPrimBufferGetLineWidth(pb,row) ; position = bufferRowColToPos(tw,pb,row,col) ; break; } break; } return(position); } /* ** refresh all text from start up to stop ** ** NOTE: ** We assume that start is always <= than stop */ void _DtTermPrimRenderRefreshTextLinear ( Widget w, XmTextPosition start, XmTextPosition stop ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; short startRow, startCol; short stopRow , stopCol; /* ** Turn XmTextPosition into a row and column */ startRow = start / (selectInfo->columns + 1); startCol = start - (startRow * (selectInfo->columns + 1)); stopRow = stop / (selectInfo->columns + 1); stopCol = stop - (stopRow * (selectInfo->columns + 1)); /* ** Accomodate the history buffer as necessary */ if (tpd->useHistoryBuffer) { startRow -= tpd->lastUsedHistoryRow; stopRow -= tpd->lastUsedHistoryRow; } /* ** Now adjust for the top of the window */ startRow -= tpd->topRow; stopRow -= tpd->topRow; /* ** refresh the first (and possibly only) line */ if (startRow == stopRow) { _DtTermPrimRefreshText((Widget)tw, startCol, startRow, stopCol, startRow); return; } _DtTermPrimRefreshText((Widget)tw, startCol, startRow, selectInfo->columns - 1, startRow); /* ** refresh the middle block (if there is one) */ if (startRow++ < stopRow) { _DtTermPrimRefreshText((Widget)tw, 0, startRow, selectInfo->columns - 1, stopRow - 1); } /* ** refresh the last line */ _DtTermPrimRefreshText((Widget)tw, 0, stopRow, stopCol, stopRow); } static void setSelection ( DtTermPrimitiveWidget tw, XmTextPosition begin, XmTextPosition end, Time selectTime, Boolean fromLoseSelection ) { TermSelectInfo selectInfo = tw->term.tpd->selectInfo; XmTextPosition oldBegin, oldEnd; Boolean disJoint; /* true if new and current are disjoint */ short selectLineBegin; short selectColBegin; short selectLineEnd; short selectColEnd; Debug('c', fprintf(stderr, ">>setSelection() starting\n")); if (selectInfo->ownPrimary == False && begin > end) { Debug('c', fprintf(stderr, ">>setSelection() finishing a\n")); return; } if (begin < 0) { begin = 0; end = 0; } if (selectInfo->ownPrimary) { /* ** we own the selection see how much (if any) of the selected ** area needs to be unhighlighted... */ if (selectInfo->begin < selectInfo->end) { /* ** We own the selection, and its highlighted... */ if ((end <= selectInfo->begin) || (begin >= selectInfo->end)) { /* ** The two areas don't intersect, simply clear the old ** area... */ Debug('c', fprintf(stderr, " new & old are disjoint\n")); selectInfo->ownPrimary = False; _DtTermPrimRenderRefreshTextLinear((Widget)tw, selectInfo->begin, selectInfo->end - 1); selectInfo->ownPrimary = True; disJoint = True; } else { /* ** There is some intersection, save the current begin ** and end so we can clean things up later. */ Debug('c', fprintf(stderr, " new & old intersect\n")); oldBegin = selectInfo->begin; oldEnd = selectInfo->end; disJoint = False; } } else { /* ** We own the selection, but nothing is highlighted... */ disJoint = True; } } else { /* ** we don't own the selection (yet), come up with some reasonable ** defaults */ disJoint = True; oldBegin = begin; oldEnd = end; } selectInfo->begin = begin; selectInfo->end = end; if (begin <= end) { if (selectInfo->ownPrimary == False) { if (!XtOwnSelection((Widget)tw, XA_PRIMARY, selectTime, _DtTermPrimSelectConvert, _DtTermPrimSelectLoseSelection, (XtSelectionDoneProc) NULL)) { /* ** XtOwnSelection failed, make a dummy call to setSelection ** (with begin > end) to clear things up... */ setSelection(tw, 1, -99, selectTime, False); } else { selectInfo->ownPrimary = True; selectInfo->primaryTime = selectTime; } } /* ** now highlight the currently selected text... */ if (selectInfo->ownPrimary) { if (disJoint == True) { /* ** the selections are disjoint, simply draw the new one */ _DtTermPrimRenderRefreshTextLinear((Widget)tw, begin, end - 1); } else { if (begin != oldBegin) { if (begin < oldBegin) { /* ** refresh from the new beginning to the old ** beginning */ _DtTermPrimRenderRefreshTextLinear((Widget)tw, begin, oldBegin - 1); } else if (oldBegin < begin) { /* ** refresh from the old beginning to the new ** beginning ** ** NOTE: in this case we want to unhighlight ** previously selected text, so we ** temporarily set ownPrimary to false */ selectInfo->ownPrimary = False; _DtTermPrimRenderRefreshTextLinear((Widget)tw, oldBegin, begin - 1); selectInfo->ownPrimary = True; } } if (end != oldEnd) { if (end < oldEnd) { /* ** refresh from the new end to the original end ** ** NOTE: in this case we want to unhighlight ** previously selected text, so we ** temporarily set ownPrimary to false */ selectInfo->ownPrimary = False; _DtTermPrimRenderRefreshTextLinear((Widget)tw, end, oldEnd - 1); selectInfo->ownPrimary = True; } else if (oldEnd < end) { /* ** refresh from the old end to the new end. */ _DtTermPrimRenderRefreshTextLinear((Widget)tw, oldEnd, end - 1); } } } } } else { if (!fromLoseSelection) { XtDisownSelection((Widget)tw, XA_PRIMARY, selectTime); } selectInfo->ownPrimary = False; } selectLineBegin = selectInfo->begin / (selectInfo->columns + 1); selectColBegin = selectInfo->begin % (selectInfo->columns + 1); selectLineEnd = (selectInfo->end - 1) / (selectInfo->columns + 1); selectColEnd = (selectInfo->end - 1) % (selectInfo->columns + 1); DebugF('c', 1, fprintf(stderr, "set selection units: %ld-%ld lines: %d-%d\n", selectInfo->begin, selectInfo->end, selectLineBegin, selectLineEnd)); if (tw->term.tpd->useHistoryBuffer && tw->term.tpd->lastUsedHistoryRow>0) { if (selectLineEnd > tw->term.tpd->lastUsedHistoryRow) { (void) _DtTermPrimBufferSetSelectLines(tw->term.tpd->historyBuffer, selectLineBegin, selectColBegin, tw->term.tpd->lastUsedHistoryRow - 1, selectInfo->columns); } else { (void) _DtTermPrimBufferSetSelectLines(tw->term.tpd->historyBuffer, selectLineBegin, selectColBegin, selectLineEnd, selectColEnd); } selectLineBegin -= tw->term.tpd->lastUsedHistoryRow; if (selectLineBegin < 0) { selectLineBegin = 0; selectColBegin = 0; } selectLineEnd -= tw->term.tpd->lastUsedHistoryRow; } if (selectLineEnd > tw->term.tpd->lastUsedRow) { (void) _DtTermPrimBufferSetSelectLines(tw->term.tpd->termBuffer, selectLineBegin, selectColBegin, tw->term.tpd->lastUsedRow, selectInfo->columns); } else { (void) _DtTermPrimBufferSetSelectLines(tw->term.tpd->termBuffer, selectLineBegin, selectColBegin, selectLineEnd, selectColEnd); } Debug('c', fprintf(stderr, ">>setSelection() finishing b\n")); } static void handleSelection ( DtTermPrimitiveWidget tw, int x, int y, Time selectTime ) { XmTextPosition position; XmTextPosition newBegin; XmTextPosition newEnd; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; Debug('c', fprintf(stderr, ">>handleSelection() starting\n")); position = xyToPos(tw, x, y); newBegin = scan(tw, position, selectInfo->scanType, scanLeft, 1, False); newEnd = scan(tw, position, selectInfo->scanType, scanRight, 1, selectInfo->scanType == XmSELECT_LINE); setSelection(tw, newBegin, newEnd, selectTime, False); if ((position - newBegin) < (newEnd - position)) { selectInfo->extendDir = scanLeft; } else { selectInfo->extendDir = scanRight; } selectInfo->origBegin = newBegin; selectInfo->origEnd = newEnd; } /************************************************************************ * * * browseScroll - timer proc that scrolls the list if the user has left * * the window with the button down. If the button has been * * released, call the standard click stuff. * * * ************************************************************************/ /* ARGSUSED */ static void browseScroll ( XtPointer closure, XtIntervalId *id ) { Widget w = (Widget) closure; DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo ; XmScrollBarWidget vsb = (XmScrollBarWidget) tw->term.verticalScrollBar; unsigned long interval; if (selectInfo->cancel) { selectInfo->selectID = 0; return; } if (!selectInfo->selectID) return; _DtTermPrimScrollComplete(w, True); if ( selectInfo->isScrollUp ) { if ( tpd->lastUsedRow-1 >= tpd->topRow + tw->term.rows) _DtTermPrimScrollText(w, 1); } else _DtTermPrimScrollText(w, -1); _DtTermPrimScrollComplete(w, True); if (selectInfo->extending) doExtendedSelection(w, XtLastTimestampProcessed(XtDisplay(w))); if (vsb) interval = (unsigned long) vsb->scrollBar.repeat_delay; else interval = 100; XSync (XtDisplay(w), False); selectInfo->selectID = XtAppAddTimeOut(XtWidgetToApplicationContext(w), interval, browseScroll, (XtPointer) w); } /* ARGSUSED */ static Boolean CheckTimerScrolling ( Widget w, XEvent *event ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; XmScrollBarWidget vsb = (XmScrollBarWidget) tw->term.verticalScrollBar; unsigned long interval; selectInfo->extend.x = event->xmotion.x; selectInfo->extend.y = event->xmotion.y; if ( (event->xmotion.y > (int) tpd->offsetY) && (event->xmotion.y < (int) (tpd->offsetY + tw->term.rows * tpd->cellHeight))) { if (selectInfo->selectID) { XtRemoveTimeOut(selectInfo->selectID); selectInfo->selectID = 0; } } else { /* above the text */ if (event->xmotion.y <= (int) tpd->offsetY) { selectInfo->extend.x = 0; selectInfo->extend.y = (int) (tpd->offsetY); selectInfo->isScrollUp = False ; /* below the text */ } else if (event->xmotion.y >= (int) (tpd->offsetY + tw->term.rows * tpd->cellHeight)) { selectInfo->extend.x = tw->core.width; selectInfo->extend.y = (int) (tpd->offsetY + tw->term.rows * tpd->cellHeight); selectInfo->isScrollUp = True ; } if (vsb) interval = (unsigned long) vsb->scrollBar.initial_delay; else interval = 200; if (!selectInfo->selectID) selectInfo->selectID = XtAppAddTimeOut(XtWidgetToApplicationContext(w), interval, browseScroll, (XtPointer) w); return True; } return False; } /* ** Create and initialize the selection specific information */ TermSelectInfo _DtTermPrimSelectCreate ( Widget w ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo; int i; selectInfo = (TermSelectInfo)XtMalloc(sizeof(TermSelectInfoRec)); selectInfo->begin = 0; selectInfo->end = 0; selectInfo->columns = tw->term.columns; selectInfo->rows = tpd->bufferRows + tpd->historyBufferRows; selectInfo->direction = (TermScanDirection) XmTEXT_FORWARD; selectInfo->extend.x = 0; selectInfo->extend.y = 0; selectInfo->extending = False; selectInfo->hint.x = 0; selectInfo->hint.y = 0; selectInfo->lastTime = 0; selectInfo->origBegin = 0; selectInfo->origEnd = 0; selectInfo->ownPrimary = False; selectInfo->threshold = 5; selectInfo->selectID = 0; selectInfo->selectType = TermSelect_NORMAL; selectInfo->scanType = defaultScanArray[0]; selectInfo->scanArraySize = XtNumber(defaultScanArray); selectInfo->scanArray = (XmTextScanType *) XtMalloc(selectInfo->scanArraySize * sizeof(XmTextScanType)); selectInfo->cancel = True; /* used by scroll selection */ selectInfo->anchor = -1; /* in case extend happens before set*/ selectInfo->sel_start = False; for (i = 0; i < selectInfo->scanArraySize; i++) { selectInfo->scanArray[i] = defaultScanArray[i]; } RegisterDropSite(w); return(selectInfo); } void _DtTermPrimSelectInitBtnEvents(Widget w) { Boolean btn1_transfer = False; XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(w)), "enableBtn1Transfer", &btn1_transfer, NULL); if (btn1_transfer) XtOverrideTranslations(w, XtParseTranslationTable(_DtTermEventBindingsCDE)); if (btn1_transfer == True) /* for btn2 extend case */ XtOverrideTranslations(w, XtParseTranslationTable(_DtTermEventBindingsCDEBtn2)); } void _DtTermPrimSelectDisown ( Widget w ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; if (selectInfo->ownPrimary == True) { XtDisownSelection(w, XA_PRIMARY, getServerTime(w)); selectInfo->ownPrimary = False ; } } void _DtTermPrimSelectDestroy ( Widget w, TermSelectInfo selectInfo ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; if (selectInfo->ownPrimary == True) { XtDisownSelection(w, XA_PRIMARY, getServerTime(w)); } selectInfo->ownPrimary = False ; XtFree((char *) selectInfo->scanArray); XtFree((char *) selectInfo); tpd->selectInfo = NULL ; } /* ** determine how much (if any) of the text is selected ** ** NOTE: ** beginCol + width will never exceed the width of the terminal ** buffer */ Boolean _DtTermPrimSelectIsInSelection ( Widget w, int row, short startCol, short width, short *selWidth ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; Boolean inSelection = True; XmTextPosition endPosition; XmTextPosition position; XmTextPosition begin; XmTextPosition end; short beginRow, beginCol; short endRow , endCol; position = rowColToPos(tw, row, startCol); endPosition = position + width; begin = selectInfo->begin; end = selectInfo->end; if ((begin >= endPosition) || (end <= position)) { /* ** outside of selection range... */ inSelection = False; } else { /* ** we're in the selection range, clip endPosition as necessary... */ if (position < begin) { /* ** we start to the left of the selection... */ inSelection = False; endPosition = MIN(endPosition, begin); } else { /* ** we must be in the selection, clip endPosition as ** necessary... */ endPosition = MIN(endPosition, end); } } *selWidth = endPosition - position; return(inSelection); } /*ARGSUSED*/ void _DtTermPrimSelectDoSelection ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectDoSelection() starting\n")); handleSelection(tw, event->xbutton.x, event->xbutton.y, event->xbutton.time); } /*ARGSUSED*/ void _DtTermPrimSelectSetHint ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { TermSelectInfo selectInfo = ((DtTermPrimitiveWidget)w)->term.tpd->selectInfo; selectInfo->hint.x = event->xbutton.x; selectInfo->hint.y = event->xbutton.y; } /*ARGSUSED*/ void _DtTermPrimSelectStart ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; XButtonEvent *btnEvent = (XButtonEvent *) event; XmTextPosition begin; XmTextPosition end; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectStart() starting\n")); /* ** set the selection hints, and scan type */ _DtTermPrimSelectSetHint(w, event, params, paramCount); setScanType(w, event); /* ** Set the current anchor point */ selectInfo->anchor = xyToPos(tw, btnEvent->x, btnEvent->y); if (selectInfo->scanType != XmSELECT_POSITION || (_DtTermPrimSelectGetSelection(w, &begin, &end) && begin != end) ) { _DtTermPrimSelectDoSelection(w, event, params, paramCount); } } /*ARGSUSED*/ void _DtTermPrimSelectGrabFocus ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; XButtonEvent *btnEvent = (XButtonEvent *) event; /* setDebugFlags("c") ; */ Debug('c', fprintf(stderr, ">>_DtTermPrimSelectGrabFocus() starting\n")); /* turn off the cursor */ _DtTermPrimCursorOff(w); selectInfo->cancel = False; tw->term.allowOsfKeysyms = True; /* normal dtterm doesn't honor these*/ /* ** constrain the button event to the terminal's text area */ if (btnEvent->x <= (int) tpd->offsetX) { /* left */ btnEvent->x = (int)(tpd->offsetX + 1); } else if (btnEvent->x >= (int)(tw->core.width - tpd->offsetX)) { /* right */ btnEvent->x = (int)(tw->core.width - tpd->offsetX - 1); } if (btnEvent->y <= (int)tpd->offsetY) { /* above */ btnEvent->y = (int)(tpd->offsetY + 1); } else if (btnEvent->y - ((int)(tpd->offsetY + ((tpd->lastUsedRow - tpd->topRow) * tpd->cellHeight))) >= selectInfo->threshold) { /* below */ btnEvent->y = (int)(tpd->offsetY + ((tpd->lastUsedRow - tpd->topRow) * tpd->cellHeight) - 1); } if (_XmGetFocusPolicy(w) == XmEXPLICIT) (void) XmProcessTraversal(w, XmTRAVERSE_CURRENT); _DtTermPrimSelectStart(w, event, params, paramCount); } static Boolean dragged ( TermSelectionHint hint, XEvent *event, int threshold ) { return ((abs(hint.x - event->xbutton.x) > threshold) || (abs(hint.y - event->xbutton.y) > threshold)); } /* ARGSUSED */ static void doExtendedSelection ( Widget w, Time eventTime ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; XmTextPosition position; XmTextPosition begin; XmTextPosition end; XmTextPosition cursorPos; float midPoint; if (selectInfo->cancel) { if (selectInfo->selectID) XtRemoveTimeOut(selectInfo->selectID); selectInfo->selectID = 0; return; } position = xyToPos(tw, selectInfo->extend.x, selectInfo->extend.y); if (!(_DtTermPrimSelectGetSelection(w, &begin, &end)) || (begin == end)) { begin = position; end = position; if ( selectInfo->anchor <0) selectInfo->anchor = position; selectInfo->origBegin = selectInfo->anchor; selectInfo->origEnd = selectInfo->anchor; midPoint = (float)selectInfo->anchor; } else { midPoint = (float) (((float)(selectInfo->origEnd - selectInfo->origBegin) / 2.0) + (float)selectInfo->origBegin); } /* ** shift anchor and direction to opposite end of the selection */ if ((float)(position) <= midPoint) { selectInfo->anchor = selectInfo->origEnd; if (!selectInfo->extending) { selectInfo->extendDir = scanLeft; } } else if ((float)(position) > midPoint) { selectInfo->anchor = selectInfo->origBegin; if (!selectInfo->extending) { selectInfo->extendDir = scanRight; } } selectInfo->extending = TRUE; /* ** check for change in extend direction */ if ((selectInfo->extendDir == scanRight && position < selectInfo->anchor) || (selectInfo->extendDir == scanLeft && position > selectInfo->anchor)) { selectInfo->extendDir = (selectInfo->extendDir == scanRight) ? scanLeft : scanRight; begin = selectInfo->begin; end = selectInfo->end; } if (selectInfo->extendDir == scanRight) { cursorPos = scan(tw, position, selectInfo->scanType, scanRight, 1, selectInfo->scanType == XmSELECT_LINE); end = cursorPos; begin = selectInfo->anchor; } else { cursorPos = scan(tw, position, selectInfo->scanType, scanLeft, 1, FALSE); begin = cursorPos; end = selectInfo->anchor; if (selectInfo->scanType == XmSELECT_WORD && (int)tw->term.tpd->cellWidth > 1) { if (position == scan (tw, begin, selectInfo->scanType, scanRight, 1, FALSE)) { begin = position; } } } setSelection(tw, begin, end, eventTime, False); } void _DtTermPrimSelectExtendStart( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; selectInfo->cancel = False; tw->term.allowOsfKeysyms = True ; _DtTermPrimSelectExtend(w, event, params, num_params); } /*ARGSUSED*/ void _DtTermPrimSelectExtend ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectExtend() starting\n")); /* turn off the cursor */ _DtTermPrimCursorOff(w); if (_XmGetFocusPolicy(w) == XmEXPLICIT) (void) XmProcessTraversal(w, XmTRAVERSE_CURRENT); if (selectInfo->cancel) return ; if ((selectInfo->hint.x > 0) || (selectInfo->hint.y > 0)) { if (dragged(selectInfo->hint, event, selectInfo->threshold)) { /* ** extend the selection */ handleSelection(tw,selectInfo->hint.x,selectInfo->hint.y, event->xbutton.time); selectInfo->hint.x = 0; selectInfo->hint.y = 0; selectInfo->extending = True; } else { /* ** do nothing */ return; } } /* ** check for timer scrolling here ** NOTE: CheckTimerScrolling(w,event) will set extend.[x|y] * selectInfo->extend.x = event->xbutton.x; * selectInfo->extend.y = event->xbutton.y; */ if (!CheckTimerScrolling(w,event) ) doExtendedSelection(w, event->xbutton.time); } /*ARGSUSED*/ void _DtTermPrimSelectExtendEnd ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectExtendEnd() starting\n")); selectInfo->cancel = True; /* used by scroll selection */ tw->term.allowOsfKeysyms = False; if (selectInfo->extending) { _DtTermPrimSelectGetSelection(w, &selectInfo->origBegin, &selectInfo->origEnd); setSelection(tw, selectInfo->origBegin, selectInfo->origEnd, event->xbutton.time, False); /* _DtTermPrimSelectExtend(w, event, params, paramCount);*/ } if (selectInfo->selectID > 0) { XtRemoveTimeOut(selectInfo->selectID); selectInfo->selectID = 0; } selectInfo->extend.x = 0; selectInfo->extend.y = 0; selectInfo->extending = False; selectInfo->hint.x = 0; selectInfo->hint.y = 0; /* turn off the cursor */ _DtTermPrimCursorOn(w); } /*ARGSUSED*/ static void doHandleTargets ( Widget w, XtPointer closure, Atom *seltype, Atom *type, XtPointer value, unsigned long *length, int *format ) { _TermSelectPrimaryRec *primSelect = (_TermSelectPrimaryRec *) closure; DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; XTextProperty tmpProp; XmTextBlockRec block; int i, status; char *pChar; char *pCharEnd; char *pCharFollow; int malloc_size=0 , numVals ; char *total_tmp_value ; char **tmp_value ; Debug('c', fprintf(stderr, ">>doHandleTargets() starting\n")); if (_XmGetFocusPolicy(w) == XmEXPLICIT) { (void) XmProcessTraversal(w, XmTRAVERSE_CURRENT); } if (*type == XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False) || *type == XA_STRING) { tmpProp.value = (unsigned char *) value; tmpProp.encoding = *type; tmpProp.format = *format; tmpProp.nitems = *length; numVals = 0; status = XmbTextPropertyToTextList(XtDisplay(w), &tmpProp, &tmp_value, &numVals ); /* ** if no conversions, numVals doesn't change */ if (numVals && (status == Success || status > 0)) { for (i = 0; i < numVals ; i++) { malloc_size += strlen(tmp_value[i]); } total_tmp_value = XtMalloc ((unsigned) malloc_size + 1); total_tmp_value[0] = '\0'; for (i = 0; i < numVals ; i++) { strcat(total_tmp_value, tmp_value[i]); } block.ptr = total_tmp_value; block.length = strlen(total_tmp_value); block.format = XmFMT_8_BIT; XFreeStringList(tmp_value); } else { malloc_size = 1; /* to force space to be freed */ total_tmp_value = XtMalloc ((unsigned)1); *total_tmp_value = '\0'; block.ptr = total_tmp_value; block.length = 0; block.format = XmFMT_8_BIT; } } else { block.ptr = (char*)value; block.length = (int) *length; /* NOTE: this causes a truncation on some architectures */ block.format = XmFMT_8_BIT; } pCharEnd = block.ptr + block.length; pCharFollow = (char *)block.ptr; for (pChar = (char *)block.ptr; pChar < pCharEnd; pChar++) { if (*pChar == '\n') { *pChar = '\r'; DtTermSubprocSend(w, (unsigned char *) pCharFollow, pChar - pCharFollow + 1); pCharFollow = pChar + 1; } } if (pCharFollow < pCharEnd) { DtTermSubprocSend(w, (unsigned char *) pCharFollow, pCharEnd - pCharFollow); } if (malloc_size != 0) XtFree(total_tmp_value); XtFree((char *)value); if (primSelect && (--primSelect->ref_count == 0)) { XtFree((char *)primSelect); } value = NULL ; } /* ** Look at the target list and determine what target to place in the ** pair. it will then do any necessary conversions before "thrusting" ** the selection value onto the receiver. this will guarantee the ** best chance at a successful exchange. */ /*ARGSUSED*/ static void handleTargets ( Widget w, XtPointer closure, Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format ) { Atom CS_OF_LOCALE; Atom COMPOUND_TEXT; Boolean supportsLocaleData; Boolean supportsCompoundText; Atom *atomPtr; _TermSelectRec *tmpAction; _TermSelectPrimaryRec *primSelect; char *abcString; XTextProperty tmpProp; int status; XtPointer closures[2]; Atom targets[2]; int i; /* ** make sure we have something to do... */ tmpAction = (_TermSelectRec *) closure; if (!length || *length == 0) { XtFree((char *)value); value = NULL; XtFree((char *)tmpAction->event); XtFree((char *)tmpAction); return; } COMPOUND_TEXT = XmInternAtom(XtDisplay(w),"COMPOUND_TEXT", False); supportsLocaleData = False; supportsCompoundText = False; abcString = "ABC"; /* characters in XPCS, so... safe */ atomPtr = (Atom *)value; tmpProp.value = NULL; status = XmbTextListToTextProperty(XtDisplay(w), &abcString, 1, (XICCEncodingStyle)XTextStyle, &tmpProp); if (status == Success) { CS_OF_LOCALE = tmpProp.encoding; } else { /* ** Kludge for failure of XmbText... to ** handle XPCS characters. Should never ** happen, but this prevents a core dump ** if X11 is broken. */ CS_OF_LOCALE = (Atom)9999; } if (tmpProp.value != NULL) { XFree((char *)tmpProp.value); } for (i = 0; i < *length; i++, atomPtr++) { if (*atomPtr == CS_OF_LOCALE) { supportsLocaleData = True; break; } if (*atomPtr == COMPOUND_TEXT) { supportsCompoundText = True; } } primSelect = (_TermSelectPrimaryRec *) XtMalloc((unsigned) sizeof(_TermSelectPrimaryRec)); /* ** If owner and I are using the same codeset, ask for it. If not, ** and if the owner supports compound text, ask for compound text. ** If not, fall back position is to ask for STRING and try to ** convert it locally. */ if (supportsLocaleData) { primSelect->target = targets[0] = CS_OF_LOCALE; } else if (supportsCompoundText) { primSelect->target = targets[0] = COMPOUND_TEXT; } else { primSelect->target = targets[0] = XA_STRING; } closures[0] = (char *)primSelect; primSelect->ref_count = 1; /* ** Make request to call doHandleTargets() with the primary selection. */ XtGetSelectionValue(w, XA_PRIMARY, targets[0], doHandleTargets, (XtPointer)primSelect, tmpAction->event->xbutton.time); XtFree((char *)value); value = NULL; XtFree((char *)tmpAction->event); XtFree((char *)tmpAction); } static char * getString ( Widget w, XmTextPosition begin, XmTextPosition end, Boolean needWideChar ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; TermBuffer tb; short beginRow, beginCol; short endRow, endCol; short thisRow; short numRows; char *buffer; char *pBuf; short len; beginRow = begin / (selectInfo->columns + 1); beginCol = begin - (beginRow * (selectInfo->columns + 1)); endRow = end / (selectInfo->columns + 1); endCol = end - (endRow * (selectInfo->columns + 1)); numRows = endRow - beginRow + 1; /* ** we need to store end - begin characters, a terminating byte, plus ** a new line for each line... ** ** NOTE: end - begin could result in a truncated long. */ buffer = XtMalloc(((int)(end - begin) + 1 + numRows) * sizeof(char) * BYTES_PER_CHAR(tpd->termBuffer)); /* ** return a null string if there is nothing to do */ if (begin == end) { *buffer = 0x00; return(buffer); } /* ** Accomodate the history buffer as necessary */ if (tpd->useHistoryBuffer) { beginRow -= tpd->lastUsedHistoryRow; endRow -= tpd->lastUsedHistoryRow; } /* ** get the first (and possibly only) line of text */ pBuf = buffer; if (beginRow == endRow) { if (beginRow < 0) { tb = tpd->historyBuffer; thisRow = beginRow + tpd->lastUsedHistoryRow; } else { tb = tpd->termBuffer; thisRow = beginRow; } len = _DtTermPrimBufferGetText(tb, thisRow, beginCol, endCol - beginCol, pBuf, needWideChar); pBuf += len; } else { if (beginRow < 0) { tb = tpd->historyBuffer; thisRow = beginRow + tpd->lastUsedHistoryRow; } else { tb = tpd->termBuffer; thisRow = beginRow; } len = _DtTermPrimBufferGetText(tb, thisRow, beginCol, selectInfo->columns - beginCol, pBuf, needWideChar); pBuf += len; if ( !_DtTermPrimBufferTestLineWrapFlag(tb,thisRow) ) { *pBuf = '\n'; /* newline */ pBuf++; } /* ** get the middle block (if there is one) */ beginRow++; while(beginRow < endRow) { if (beginRow < 0) { tb = tpd->historyBuffer; thisRow = beginRow + tpd->lastUsedHistoryRow; } else { tb = tpd->termBuffer; thisRow = beginRow; } len = _DtTermPrimBufferGetText(tb, thisRow, 0, selectInfo->columns , pBuf, needWideChar); pBuf += len; /* if (len != 0 && len < selectInfo->columns ) { */ if ( !_DtTermPrimBufferTestLineWrapFlag(tb,thisRow) ) { *pBuf = '\n'; /* newline */ pBuf++; } beginRow++; } /* ** get the last line */ if (endRow < 0) { tb = tpd->historyBuffer; thisRow = endRow + tpd->lastUsedHistoryRow; } else { tb = tpd->termBuffer; thisRow = endRow; } len = _DtTermPrimBufferGetText(tb, thisRow, 0, endCol, pBuf, needWideChar); pBuf += len; } *pBuf = 0x00; return(buffer); } /* ** Request targets from selection owner. */ static void getTargets ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { _TermSelectRec *tmp; tmp = (_TermSelectRec*)XtMalloc(sizeof(_TermSelectRec)); /* ** Request targets from the selection owner so you can decide what to ** request. The decision process and request for the selection is ** taken care of in handleTargets(). */ tmp->event = (XEvent *) XtMalloc(sizeof(XEvent)); memcpy((void *)tmp->event, (void *)event, sizeof(XEvent)); tmp->params = params; tmp->num_params = paramCount; XtGetSelectionValue(w, XA_PRIMARY, XmInternAtom(XtDisplay(w), "TARGETS", False), handleTargets, (XtPointer)tmp, event->xbutton.time); } Boolean _DtTermPrimSelectConvert ( Widget w, Atom *selection, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format ) { Atom TARGETS = XmInternAtom(XtDisplay(w), "TARGETS", False); Atom CS_OF_LOCALE; Atom COMPOUND_TEXT = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False); Atom TEXT = XmInternAtom(XtDisplay(w), "TEXT", False); Atom MOTIF_DROP = XmInternAtom(XtDisplay(w), "_MOTIF_DROP", False); int maxTargets = 10; int targetCount; int status; Widget widget; Boolean ownPrimary; XmTextPosition begin; XmTextPosition end; char *tmpValue; char *tmpString = "ABC"; /* characters in XPCS, so... safe */ XTextProperty tmpProp; XtPointer c_ptr; Arg args[1]; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectConvert() starting\n")); if (*selection == MOTIF_DROP) { XtSetArg(args[0], XmNclientData, &c_ptr); XtGetValues(w, args, 1); widget = (Widget)c_ptr; } else widget = w; if (widget == NULL) return False; tmpProp.value = NULL; status = XmbTextListToTextProperty(XtDisplay(widget), &tmpString, 1, (XICCEncodingStyle)XTextStyle, &tmpProp); if (status == Success) { CS_OF_LOCALE = tmpProp.encoding; } else { /* ** XmbTextList... SHOULD never fail for ** XPCS character. But if it does, this ** prevents a core dump. */ CS_OF_LOCALE = (Atom) 9999; } if (tmpProp.value != NULL) XFree((char *) tmpProp.value); if (*selection == XA_PRIMARY || *selection == MOTIF_DROP) { ownPrimary = _DtTermPrimSelectGetSelection(widget, &begin, &end); } else { return(False); } if (*target == TARGETS) { Atom *targets = (Atom *)XtMalloc((unsigned)(maxTargets * sizeof(Atom))); /* ** Xt should take care of TIME_STAMP for us. */ targetCount = 0; *value = (XtPointer)targets; *targets++ = TARGETS; targetCount++; if (!isDebugFSet('s', 1)) { *targets++ = COMPOUND_TEXT; targetCount++; } if (!isDebugFSet('s', 2)) { *targets++ = CS_OF_LOCALE; targetCount++; } if (!isDebugFSet('s', 3)) { *targets++ = TEXT; targetCount++; } if (!isDebugFSet('s', 4)) { *targets++ = XA_STRING; targetCount++; } *type = XA_ATOM; *length = (targetCount * sizeof(Atom)) >> 2; /* convert to work count */ *format = 32; } else if (!ownPrimary) { return(False); } else if ((*target == XA_STRING && !isDebugFSet('s', 4)) || (*target == COMPOUND_TEXT && !isDebugFSet('s', 1))) { tmpValue = getString(widget, begin, end, False); tmpProp.value = NULL; if ((*target == XA_STRING) && !isDebugFSet('s', 4)) { *type = (Atom) XA_STRING; *format = 8; status = XmbTextListToTextProperty(XtDisplay(widget), &tmpValue, 1, (XICCEncodingStyle)XStringStyle, &tmpProp); } else if ((*target == COMPOUND_TEXT) && !isDebugFSet('s',1)) { *type = COMPOUND_TEXT; *format = 8; status = XmbTextListToTextProperty(XtDisplay(widget), &tmpValue, 1, (XICCEncodingStyle)XCompoundTextStyle, &tmpProp); } XtFree(tmpValue); if (status == Success || status > 0) { /* ** NOTE: casting tmpProp.nitems could result in a truncated long. */ if (tmpProp.nitems > 0) *value = (XtPointer) XtMalloc((unsigned)tmpProp.nitems); else *value = (XtPointer) XtMalloc(1); *length = tmpProp.nitems; memcpy((void*)*value, (void*)tmpProp.value, (unsigned)tmpProp.nitems); if (tmpProp.value != NULL) XFree((char*)tmpProp.value); } else { *value = NULL; *length = 0; if (tmpProp.value != NULL) XFree((char*)tmpProp.value); return(False); } } else if (((*target == CS_OF_LOCALE) && !isDebugFSet('s', 2)) || (*target == TEXT && !isDebugFSet('s', 3))) { *type = CS_OF_LOCALE; *format = 8; *value = (XtPointer)getString(widget, begin, end, False); *length = strlen((char*) *value); } else { *value = NULL; *length = 0; return(False); } Debug('c', fprintf(stderr, ">>_DtTermPrimSelectConvert() exiting\n")); return(True); } void _DtTermPrimSelectLoseSelection ( Widget w, Atom *selection ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; Boolean restoreCursor = False; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectLoseSelection() starting\n")); if (*selection == XA_PRIMARY && selectInfo->ownPrimary) { /* ** We've lost the primary selection, make a dummy call to ** setSelection (with begin > end) to clear things up... */ /* turn off the cursor */ if (tw->term.tpd->cursorState != CURSORoff) { _DtTermPrimCursorOff(w); restoreCursor = True; } setSelection(tw, 1, -99, XtLastTimestampProcessed(XtDisplay(w)), True); /* turn on the cursor */ if (restoreCursor) { _DtTermPrimCursorOn(w); } } Debug('c', fprintf(stderr, ">>_DtTermPrimSelectLoseSelection() exiting\n")); } /*ARGSUSED*/ void _DtTermPrimSelectBDragRelease ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { TermSelectInfo selectInfo = ((DtTermPrimitiveWidget)w)->term.tpd->selectInfo; XButtonEvent *btnEvent = (XButtonEvent *) event; Debug('c', fprintf(stderr, ">>_DtTermPrimSelectBDragRelease() starting\n")); /* Work around for intrinsic bug. Remove once bug is fixed. ** this is for drag/drop */ XtUngrabPointer(w, btnEvent->time); if ( selectInfo->sel_start ) getTargets(w, event, params, paramCount); } /*ARGSUSED*/ void _DtTermPrimSelectInsert ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; if (!selectInfo->cancel) _DtTermPrimSelectBDragRelease(w, event, params, paramCount); selectInfo->cancel = True ; /* turn on the cursor */ _DtTermPrimCursorOn(w); } Boolean _DtTermPrimSelectIsAboveSelection ( Widget w, short row, short col ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; XmTextPosition curPos, endPos; endPos = selectInfo->end ; curPos = rowColToPos(tw,row,col) ; if ( curPos < endPos ) return(True) ; else return(False) ; } void _DtTermPrimSelectResize ( Widget w ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; _DtTermPrimSelectDisown(w) ; selectInfo->columns = tw->term.columns ; } extern void _DtTermPrimSelectMoveLines ( Widget w, short src, short dest, short len ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; short selectLineBegin; short selectLineEnd; TermBuffer pb; short row,col; posToBufferRowCol (tw, selectInfo->begin, &pb, &row, &col); /* if there are no lines, etc. return... */ if ((len <= 0) || (src == dest) || !selectInfo->ownPrimary || pb == tw->term.tpd->historyBuffer ) { return; } if (row >= src && row < (src + len)) { selectInfo->begin -= (src - dest) * (selectInfo->columns + 1); selectInfo->end -= (src - dest) * (selectInfo->columns + 1); } } extern void _DtTermPrimSelectDeleteLines ( Widget w, short src, short len ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; short selectLineBegin; short selectLineEnd; TermBuffer pb; short row,col; posToBufferRowCol (tw, selectInfo->begin, &pb, &row, &col); /* if there are no lines, etc. return... */ if ((len <= 0) || !selectInfo->ownPrimary || ((tw->term.tpd->scrollLockTopRow > 0 || (tw->term.tpd->scrollLockBottomRow < tw->term.rows-1)) && row < tw->term.tpd->scrollLockTopRow)) { return; } /* figure out what the begin line is... */ selectLineBegin = selectInfo->begin / (selectInfo->columns + 1); /* if the beginning of the selection is after the source, we need to * move the selection up... */ if (selectLineBegin > src) { selectInfo->begin -= len * (selectInfo->columns + 1); selectInfo->end -= len * (selectInfo->columns + 1); if (selectInfo->begin < 0) { (void) _DtTermPrimSelectDisown(w); } } } extern void _DtTermPrimSelectInsertLines ( Widget w, short src, short len ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; short selectLineBegin; short selectLineEnd; /* if there are no lines, return... */ if ((len <= 0) || !selectInfo->ownPrimary) { return; } /* figure out what the begin line is... */ selectLineBegin = selectInfo->begin / (selectInfo->columns + 1); /* if the beginning of the selection is at or after the source, we need to * move the selection up... */ if (selectLineBegin >= src) { selectInfo->begin += len * (selectInfo->columns + 1); selectInfo->end += len * (selectInfo->columns + 1); } } void _DtTermPrimSelectAll ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; DtTermPrimData tpd = tw->term.tpd; TermSelectInfo selectInfo = tpd->selectInfo; XButtonEvent *btnEvent = (XButtonEvent *) event; XmTextPosition begin; XmTextPosition end; /* position not used in XmSELECT_ALL case */ begin = scan(tw, (XmTextPosition) 0, XmSELECT_ALL, scanLeft, 1, False); end = scan(tw, (XmTextPosition) 0, XmSELECT_ALL, scanRight, 1, selectInfo->scanType == XmSELECT_LINE); /* turn off the cursor */ _DtTermPrimCursorOff(w); setSelection(tw, begin, end, event->xbutton.time, False); /* turn on the cursor */ _DtTermPrimCursorOn(w); } void _DtTermPrimSelectPage ( Widget w, XEvent *event, String *params, Cardinal *paramCount ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; XButtonEvent *btnEvent = (XButtonEvent *) event; XmTextPosition begin, end; short lastRow, width; TermBuffer pb; begin = xyToPos(tw, 1, 1); end = xyToPos(tw, tw->core.width-1, tw->core.height-1); /* turn off the cursor */ _DtTermPrimCursorOff(w); setSelection(tw, begin, end, event->xbutton.time, False); /* turn on the cursor */ _DtTermPrimCursorOn(w); } /* * DROP SITE code */ static XContext _DtTermDNDContext = 0; static void DropTransferCallback( Widget w, XtPointer closure, Atom *seltype, Atom *type, XtPointer value, unsigned long *length, int *format ) { _DtTermDropTransferRec *transfer_rec = (_DtTermDropTransferRec *) closure; DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)transfer_rec->widget; /* When type = NULL, we are assuming a DELETE request has been requested */ if (*type == 0) { if (value) { XtFree((char *)value); value = NULL; } return; } doHandleTargets((Widget)tw,NULL,seltype,type,value,length,format) ; if (transfer_rec->move) { XmDropTransferEntryRec transferEntries[1]; XmDropTransferEntryRec *transferList = NULL; transferEntries[0].client_data = (XtPointer) transfer_rec; transferEntries[0].target = XmInternAtom(XtDisplay(w),"DELETE", False); XmDropTransferAdd(w, transferEntries, 1); } } static void DeleteDropContext( Widget w ) { Display *display = XtDisplay(w); Screen *screen = XtScreen(w); XDeleteContext(display, (Window)screen, _DtTermDNDContext); } static void SetDropContext( Widget w ) { Display *display = XtDisplay(w); Screen *screen = XtScreen(w); _DtTermProcessLock(); if (_DtTermDNDContext == 0) _DtTermDNDContext = XUniqueContext(); _DtTermProcessUnlock(); XSaveContext(display, (Window)screen, _DtTermDNDContext, (XPointer)w); } typedef struct _dropDestroyCBClientData { _DtTermDropTransferRec *transfer_rec; XtCallbackRec *dropDestroyCB; } dropDestroyCBClientData; /* ARGSUSED */ static void DropDestroyCB( Widget w, XtPointer clientData, XtPointer callData ) { dropDestroyCBClientData *ptr = (dropDestroyCBClientData *) clientData; DeleteDropContext(w); if (ptr) { if (ptr->transfer_rec) XtFree((char *) ptr->transfer_rec); if (ptr->dropDestroyCB) XtFree((char *) ptr->dropDestroyCB); XtFree((char *) ptr); } } static void HandleDrop( Widget w, XmDropProcCallbackStruct *cb ) { Widget drag_cont, initiator; /* XmTextWidget tw = (XmTextWidget) w; */ DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; Cardinal numExportTargets, n; Atom *exportTargets; Arg args[10]; XmTextPosition insert_pos, left, right; XtCallbackRec *dropDestroyCB, *dd_cb; dropDestroyCBClientData *clientData; clientData = (dropDestroyCBClientData *) XtMalloc(sizeof(dropDestroyCBClientData)); dropDestroyCB = dd_cb = (XtCallbackRec *) XtMalloc(2 * sizeof (XtCallbackRec)); clientData->dropDestroyCB = dropDestroyCB; dd_cb->callback = DropDestroyCB; dd_cb->closure = NULL; dd_cb++; dd_cb->callback = (XtCallbackProc) NULL; dd_cb->closure = NULL; drag_cont = cb->dragContext; n = 0; XtSetArg(args[n], XmNsourceWidget, &initiator); n++; XtSetArg(args[n], XmNexportTargets, &exportTargets); n++; XtSetArg(args[n], XmNnumExportTargets, &numExportTargets); n++; XtGetValues((Widget) drag_cont, args, n); { XmDropTransferEntryRec transferEntries[2]; XmDropTransferEntryRec *transferList = NULL; Atom TEXT = XmInternAtom(XtDisplay(w), "TEXT", False); Atom COMPOUND_TEXT = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False); Atom CS_OF_LOCALE; char * tmp_string = "ABC"; /* these are characters in XPCS, so... safe */ XTextProperty tmp_prop; _DtTermDropTransferRec *transfer_rec; Cardinal numTransfers = 0; Boolean locale_found = False; Boolean c_text_found = False; Boolean string_found = False; Boolean text_found = False; int status; tmp_prop.value = NULL; status = XmbTextListToTextProperty(XtDisplay(w), &tmp_string, 1, (XICCEncodingStyle)XTextStyle, &tmp_prop); if (status == Success) CS_OF_LOCALE = tmp_prop.encoding; else CS_OF_LOCALE = 99999; /* XmbTextList... should never fail for XPCS * characters. But just in case someones * Xlib is broken, this prevents a core dump. */ if (tmp_prop.value != NULL) XFree((char *)tmp_prop.value); /* intialize data to send to drop transfer callback */ transfer_rec = (_DtTermDropTransferRec *) XtMalloc(sizeof(_DtTermDropTransferRec)); clientData->transfer_rec = transfer_rec; transfer_rec->widget = w; /* don't actually need all of this for dtterm - it was from Text widget *transfer_rec->insert_pos = insert_pos; *transfer_rec->num_chars = 0; *transfer_rec->timestamp = cb->timeStamp; * */ if (cb->operation & XmDROP_MOVE) { transfer_rec->move = True; } else { transfer_rec->move = False; } transferEntries[0].client_data = (XtPointer) transfer_rec; transferList = transferEntries; numTransfers = 1; for (n = 0; n < numExportTargets; n++) { if (exportTargets[n] == CS_OF_LOCALE) { transferEntries[0].target = CS_OF_LOCALE; locale_found = True; break; } if (exportTargets[n] == COMPOUND_TEXT) c_text_found = True; if (exportTargets[n] == XA_STRING) string_found = True; if (exportTargets[n] == TEXT) text_found = True; } n = 0; if (locale_found || c_text_found || string_found || text_found) { if (!locale_found) { if (c_text_found) transferEntries[0].target = COMPOUND_TEXT; else if (string_found) transferEntries[0].target = XA_STRING; else transferEntries[0].target = TEXT; } if ( cb->operation & (XmDROP_COPY|XmDROP_MOVE) ) { XtSetArg(args[n], XmNdropTransfers, transferList); n++; XtSetArg(args[n], XmNnumDropTransfers, numTransfers); n++; } else { XtSetArg(args[n], XmNtransferStatus, XmTRANSFER_FAILURE); n++; XtSetArg(args[n], XmNnumDropTransfers, 0); n++; } } else { XtSetArg(args[n], XmNtransferStatus, XmTRANSFER_FAILURE); n++; XtSetArg(args[n], XmNnumDropTransfers, 0); n++; } dropDestroyCB->closure = (XtPointer) clientData; XtSetArg(args[n], XmNdestroyCallback, dropDestroyCB); n++; XtSetArg(args[n], XmNtransferProc, DropTransferCallback); n++; } SetDropContext(w); XmDropTransferStart(drag_cont, args, n); } /* ARGSUSED */ static void DropProcCallback( Widget w, XtPointer client, XtPointer call ) { XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *) call; if (cb->dropAction != XmDROP_HELP) { HandleDrop(w, cb); } else { Arg args[2]; XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE); XtSetArg(args[1], XmNnumDropTransfers, 0); XmDropTransferStart(cb->dragContext, args, 2); } } static void RegisterDropSite( Widget w ) { Atom targets[4]; Arg args[10]; int n; char * tmp_string = "ABC"; /* these are characters in XPCS, so... safe */ XTextProperty tmp_prop; int status = 0; tmp_prop.value = NULL; status = XmbTextListToTextProperty(XtDisplay(w), &tmp_string, 1, (XICCEncodingStyle)XTextStyle, &tmp_prop); if (status == Success) targets[0] = tmp_prop.encoding; else targets[0] = 99999; /* XmbTextList... should never fail for XPCS * characters. But just in case someones * Xlib is broken, this prevents a core dump. */ if (tmp_prop.value != NULL) XFree((char *)tmp_prop.value); targets[1] = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False); targets[2] = XA_STRING; targets[3] = XmInternAtom(XtDisplay(w), "TEXT", False); n = 0; XtSetArg(args[n], XmNimportTargets, targets); n++; XtSetArg(args[n], XmNnumImportTargets, 4); n++; /* XtSetArg(args[n], XmNdragProc, DragProcCallback); n++; */ XtSetArg(args[n], XmNdropProc, DropProcCallback); n++; XmDropSiteRegister(w, args, n); } /* * DRAG SITE code */ /* ARGSUSED */ static void StartDrag( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; Atom targets[4]; char * tmp_string = "ABC"; /* these are characters in XPCS, so... safe */ XTextProperty tmp_prop; int status = 0; Cardinal num_targets = 0; Widget drag_icon; Arg args[10]; int n = 0; tmp_prop.value = NULL; status = XmbTextListToTextProperty(XtDisplay(w), &tmp_string, 1, (XICCEncodingStyle)XTextStyle, &tmp_prop); if (status == Success) targets[num_targets++] = tmp_prop.encoding; else targets[num_targets++] = 99999; /* XmbTextList... should never fail * for XPCS characters. But just in * case someones Xlib is broken, * this prevents a core dump. */ if (tmp_prop.value != NULL) XFree((char *)tmp_prop.value); targets[num_targets++] = XmInternAtom(XtDisplay(w), "COMPOUND_TEXT", False); targets[num_targets++] = XA_STRING; targets[num_targets++] = XmInternAtom(XtDisplay(w), "TEXT", False); drag_icon = (Widget) XmeGetTextualDragIcon(w); n = 0; XtSetArg(args[n], XmNcursorBackground, tw->core.background_pixel); n++; XtSetArg(args[n], XmNcursorForeground, tw->primitive.foreground); n++; XtSetArg(args[n], XmNsourceCursorIcon, drag_icon); n++; XtSetArg(args[n], XmNexportTargets, targets); n++; XtSetArg(args[n], XmNnumExportTargets, num_targets); n++; XtSetArg(args[n], XmNconvertProc, _DtTermPrimSelectConvert); n++; XtSetArg(args[n], XmNclientData, w); n++; XtSetArg(args[n], XmNdragOperations, ( XmDROP_COPY)); n++; (void) XmDragStart(w, event, args, n); } static Position GetXFromPos(Widget w, XmTextPosition pos) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; DtTermPrimData tpd = tw->term.tpd; TermBuffer pb; short row,col; TermCharInfoRec charInfoRec ; posToBufferRowCol(tw,pos,&pb,&row,&col) ; return(tpd->offsetX+col*tpd->cellWidth); } /* ARGSUSED */ void _DtTermPrimSelectProcessBDrag( Widget w, XEvent *event, char **params, Cardinal *num_params ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; TermSelectInfo selectInfo = ((DtTermPrimitiveWidget)w)->term.tpd->selectInfo; XmTextPosition position, left, right; Position left_x, left_y, right_x, right_y; /* InputData data = tw->text.input->data; */ selectInfo->cancel = False; position = xyToPos(tw, event->xbutton.x, event->xbutton.y); if (_DtTermPrimSelectGetSelection(w, &left, &right) && (right != left)) { if ((position > left && position < right) || (position == left && event->xbutton.x > GetXFromPos(w, left)) || (position == right && event->xbutton.x < GetXFromPos(w, right))) { selectInfo->sel_start = False; StartDrag(w, event, params, num_params); } else { selectInfo->sel_start = True ; } } else selectInfo->sel_start = True ; } /* This is the menu interface for copy clipboard */ Boolean _DtTermPrimSelectCopyClipboard ( Widget w, Time copy_time ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; XmTextPosition begin; XmTextPosition end; char *selected_string = NULL; /* text selection */ long item_id = 0L; /* clipboard item id */ long data_id = 0L; /* clipboard data id */ int status; /* clipboard status */ XmString clip_label; XTextProperty tmp_prop; Display *display = XtDisplay(w); Window window = XtWindow(w); char *atom_name; if ( _DtTermPrimSelectGetSelection(w, &begin, &end) && begin != end ) { selected_string = getString(w, begin, end, False); } /* * Using the Xm clipboard facilities, * copy the selected text to the clipboard */ tmp_prop.value = NULL; if (selected_string != NULL) { clip_label = XmStringCreateLocalized ("XM_TERM"); /* start copy to clipboard */ status = XmClipboardStartCopy(display, window, clip_label, copy_time, w, NULL, &item_id); if (status != ClipboardSuccess) { XtFree(selected_string); XmStringFree(clip_label); return False; } status = XmbTextListToTextProperty(display, &selected_string, 1, (XICCEncodingStyle)XStdICCTextStyle, &tmp_prop); if (status != Success && status <= 0) { XmClipboardCancelCopy(display, window, item_id); XtFree(selected_string); XmStringFree(clip_label); return False; } atom_name = XGetAtomName(display, tmp_prop.encoding); /* move the data to the clipboard */ status = XmClipboardCopy(display, window, item_id, atom_name, (XtPointer)tmp_prop.value, tmp_prop.nitems, 0, &data_id); XtFree(atom_name); if (status != ClipboardSuccess) { XmClipboardCancelCopy(display, window, item_id); XFree((char*)tmp_prop.value); XmStringFree(clip_label); return False; } /* end the copy to the clipboard */ status = XmClipboardEndCopy (display, window, item_id); XtFree((char*)tmp_prop.value); XmStringFree(clip_label); if (status != ClipboardSuccess) return False; } else return False; if (selected_string!=NULL) XtFree(selected_string); return True; } /* This is the event interface for copy clipboard */ void _DtTermPrimSelectCopyClipboardEventIF ( Widget w, XEvent *event, String *params, Cardinal *num_params ) { _DtTermPrimSelectCopyClipboard(w,event->xkey.time) ; } /* * Retrieves the current data from the clipboard * and paste it at the current cursor position */ Boolean _DtTermPrimSelectPasteClipboard ( Widget w ) { XmTextPosition sel_left = 0; XmTextPosition sel_right = 0; XmTextPosition paste_pos_left, paste_pos_right, cursorPos; int status; /* clipboard status */ char * buffer; /* temporary text buffer */ unsigned long length; /* length of buffer */ unsigned long outlength = 0L; /* length of bytes copied */ long private_id = 0L; /* id of item on clipboard */ Boolean dest_disjoint = True; XmTextBlockRec block, newblock; Display *display = XtDisplay(w); Window window = XtWindow(w); Boolean get_ct = False; Boolean freeBlock; XTextProperty tmp_prop; int malloc_size = 0; int num_vals; char **tmp_value; char * total_tmp_value = NULL; int i; status = XmClipboardInquireLength(display, window, "STRING", &length); if (status == ClipboardNoData || length == 0) { status = XmClipboardInquireLength(display, window, "COMPOUND_TEXT", &length); if (status == ClipboardNoData || length == 0) return False; get_ct = True; } /* malloc length of clipboard data */ buffer = XtMalloc((unsigned) length); if (!get_ct) { status = XmClipboardRetrieve(display, window, "STRING", buffer, length, &outlength, &private_id); } else { status = XmClipboardRetrieve(display, window, "COMPOUND_TEXT", buffer, length, &outlength, &private_id); } if (status != ClipboardSuccess) { XmClipboardEndRetrieve(display, window); XtFree(buffer); return False; } tmp_prop.value = (unsigned char *) buffer; if (!get_ct) tmp_prop.encoding = XA_STRING; else tmp_prop.encoding = XmInternAtom(display, "COMPOUND_TEXT", False); tmp_prop.format = 8; tmp_prop.nitems = outlength; num_vals = 0; status = XmbTextPropertyToTextList(display, &tmp_prop, &tmp_value, &num_vals); /* if no conversions, num_vals doesn't change */ if (num_vals && (status == Success || status > 0)) { for (i = 0; i < num_vals ; i++) malloc_size += strlen(tmp_value[i]); total_tmp_value = XtMalloc ((unsigned) malloc_size + 1); total_tmp_value[0] = '\0'; for (i = 0; i < num_vals ; i++) strcat(total_tmp_value, tmp_value[i]); block.ptr = total_tmp_value; block.length = strlen(total_tmp_value); block.format = XmFMT_8_BIT; XFreeStringList(tmp_value); } else { malloc_size = 1; /* to force space to be freed */ total_tmp_value = XtMalloc ((unsigned)1); *total_tmp_value = '\0'; block.ptr = total_tmp_value; block.length = 0; block.format = XmFMT_8_BIT; } /* add new text */ if ( block.length ) { char *pChar, *pCharEnd, *pCharFollow; pCharEnd = block.ptr + block.length; pCharFollow = (char *)block.ptr; for (pChar = (char *)block.ptr; pChar < pCharEnd; pChar++) { if (*pChar == '\n') { *pChar = '\r'; DtTermSubprocSend(w, (unsigned char *) pCharFollow, pChar - pCharFollow + 1); pCharFollow = pChar + 1; } } if (pCharFollow < pCharEnd) { DtTermSubprocSend(w, (unsigned char *) pCharFollow, pCharEnd - pCharFollow); } } XtFree(buffer); if (malloc_size != 0) XtFree(total_tmp_value); (void) _DtTermPrimCursorOn(w); return True; } /* This is the event interface for paste clipboard */ void _DtTermPrimSelectPasteClipboardEventIF ( Widget w, XEvent *event, String *params, Cardinal *num_params ) { _DtTermPrimSelectPasteClipboard(w) ; } /* * This is for the SUN two button mouse */ static Bool LookForButton ( Display * display, XEvent * event, XPointer arg) { #define DAMPING 5 #define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2) if( event->type == MotionNotify) { XEvent * press = (XEvent *) arg; if (ABS_DELTA(press->xbutton.x_root, event->xmotion.x_root) > DAMPING || ABS_DELTA(press->xbutton.y_root, event->xmotion.y_root) > DAMPING) return(True); } else if (event->type == ButtonRelease) return(True); return(False); } /* ARGSUSED */ static Boolean XmTestInSelection( Widget w, XEvent *event ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; XmTextPosition position, left, right; Position left_x, right_x, dummy; position = xyToPos(tw, event->xbutton.x, event->xbutton.y); if ((!(_DtTermPrimSelectGetSelection(w, &left, &right) && (left != right && (position > left && position < right))) || (position == left && event->xbutton.x > GetXFromPos(w, left)) || (position == right && event->xbutton.x < GetXFromPos(w, right))) || /* or if it is part of a multiclick sequence */ (event->xbutton.time > selectInfo->lastTime && event->xbutton.time - selectInfo->lastTime < XtGetMultiClickTime(XtDisplay((Widget)w))) ) return(False); else { /* The determination of whether this is a transfer drag cannot be made until a Motion event comes in. It is not a drag as soon as a ButtonUp event happens or the MultiClickTimeout expires. */ XEvent new; XPeekIfEvent(XtDisplay(w), &new, LookForButton, (XPointer)event); switch (new.type) { case MotionNotify: return(True); break; case ButtonRelease: return(False); break; } return(False); } } #define SELECTION_ACTION 0 #define TRANSFER_ACTION 1 /* ARGSUSED */ void _DtTermPrimSelect2ButtonMouse( Widget w, XEvent *event, char **params, Cardinal *num_params ) { /* This action happens when Button1 is pressed and the Selection and Transfer are integrated on Button1. It is passed two parameters: the action to call when the event is a selection, and the action to call when the event is a transfer. */ if (*num_params != 2 /* || !XmIsTextField(w) */) return; if (XmTestInSelection(w, event)) XtCallActionProc(w, params[TRANSFER_ACTION], event, params, *num_params); else XtCallActionProc(w, params[SELECTION_ACTION], event, params, *num_params); } void _DtTermPrimSelectProcessCancel( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget)w; TermSelectInfo selectInfo = tw->term.tpd->selectInfo; XmTextPosition left_x, right_x; XmParentInputActionRec p_event ; if (!tw->term.allowOsfKeysyms) { _DtTermPrimActionKeyInput(w,event,params,num_params); return; } selectInfo->cancel = True ; /* turn off the cursor */ _DtTermPrimCursorOff(w); /* reset to origLeft and origRight */ setSelection (tw, selectInfo->origBegin, selectInfo->origEnd, event->xkey.time, False) ; /* turn on the cursor */ _DtTermPrimCursorOn(w); if (selectInfo->selectID) { XtRemoveTimeOut(selectInfo->selectID); selectInfo->selectID = 0; } }