Beispiel #1
0
/*
** Do a shell command, with the options allowed to users (input source,
** output destination, save first and load after) in the shell commands
** menu.
*/
void DoShellMenuCmd(WindowInfo *window, const char *command,
        int input, int output,
	int outputReplacesInput, int saveFirst, int loadAfter, int fromMacro) 
{
    int flags = 0;
    char *text;
    char *subsCommand, fullName[MAXPATHLEN];
    int left, right, textLen;
    int pos, line, column;
    char lineNumber[11];
    WindowInfo *inWindow = window;
    Widget outWidget;

    /* Can't do two shell commands at once in the same window */
    if (window->shellCmdData != NULL) {
    	XBell(TheDisplay, 0);
    	return;
    }

    /* Substitute the current file name for % and the current line number
       for # in the shell command */
    strcpy(fullName, window->path);
    strcat(fullName, window->filename);
    pos = TextGetCursorPos(window->lastFocus);
    TextPosToLineAndCol(window->lastFocus, pos, &line, &column);
    sprintf(lineNumber, "%d", line);
    
    subsCommand = shellCommandSubstitutes(command, fullName, lineNumber);
    if (subsCommand == NULL)
    {
        DialogF(DF_ERR, window->shell, 1, "Shell Command",
                "Shell command is too long due to\n"
                "filename substitutions with '%%' or\n"
                "line number substitutions with '#'", "OK");
        return;
    }

    /* Get the command input as a text string.  If there is input, errors
      shouldn't be mixed in with output, so set flags to ERROR_DIALOGS */
    if (input == FROM_SELECTION) {
	text = BufGetSelectionText(window->buffer);
	if (*text == '\0') {
    	    XtFree(text);
            free(subsCommand);
    	    XBell(TheDisplay, 0);
    	    return;
    	}
    	flags |= ACCUMULATE | ERROR_DIALOGS;
    } else if (input == FROM_WINDOW) {
	text = BufGetAll(window->buffer);
    	flags |= ACCUMULATE | ERROR_DIALOGS;
    } else if (input == FROM_EITHER) {
	text = BufGetSelectionText(window->buffer);
	if (*text == '\0') {
	    XtFree(text);
	    text = BufGetAll(window->buffer);
    	}
    	flags |= ACCUMULATE | ERROR_DIALOGS;
    } else /* FROM_NONE */
    	text = NULL;
    
    /* If the buffer was substituting another character for ascii-nuls,
       put the nuls back in before exporting the text */
    if (text != NULL) {
	textLen = strlen(text);
	BufUnsubstituteNullChars(text, window->buffer);
    } else
	textLen = 0;
    
    /* Assign the output destination.  If output is to a new window,
       create it, and run the command from it instead of the current
       one, to free the current one from waiting for lengthy execution */
    if (output == TO_DIALOG) {
    	outWidget = NULL;
	flags |= OUTPUT_TO_DIALOG;
    	left = right = 0;
    } else if (output == TO_NEW_WINDOW) {
    	EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL, window->path);
    	outWidget = WindowList->textArea;
	inWindow = WindowList;
    	left = right = 0;
	CheckCloseDim();
    } else { /* TO_SAME_WINDOW */
    	outWidget = window->lastFocus;
    	if (outputReplacesInput && input != FROM_NONE) {
    	    if (input == FROM_WINDOW) {
    		left = 0;
    		right = window->buffer->length;
    	    } else if (input == FROM_SELECTION) {
    	    	GetSimpleSelection(window->buffer, &left, &right);
	        flags |= ACCUMULATE | REPLACE_SELECTION;
    	    } else if (input == FROM_EITHER) {
    	    	if (GetSimpleSelection(window->buffer, &left, &right))
	            flags |= ACCUMULATE | REPLACE_SELECTION;
	        else {
	            left = 0;
	            right = window->buffer->length;
	        }
	    }
    	} else {
	    if (GetSimpleSelection(window->buffer, &left, &right))
	        flags |= ACCUMULATE | REPLACE_SELECTION;
	    else
    		left = right = TextGetCursorPos(window->lastFocus);
    	}
    }
    
    /* If the command requires the file be saved first, save it */
    if (saveFirst) {
    	if (!SaveWindow(window)) {
    	    if (input != FROM_NONE)
    		XtFree(text);
            free(subsCommand);
    	    return;
	}
    }
    
    /* If the command requires the file to be reloaded after execution, set
       a flag for issueCommand to deal with it when execution is complete */
    if (loadAfter)
    	flags |= RELOAD_FILE_AFTER;
    	
    /* issue the command */
    issueCommand(inWindow, subsCommand, text, textLen, flags, outWidget, left,
	    right, fromMacro);
    free(subsCommand);
}
/*
** Start the process of dragging the current primary-selected text across
** the window (move by dragging, as opposed to dragging to create the
** selection)
*/
void BeginBlockDrag(TextWidget tw)
{
    textDisp *textD = tw->text.textD;
    textBuffer *buf = textD->buffer;
    int fontHeight = textD->fontStruct->ascent + textD->fontStruct->descent;
    int fontWidth = textD->fontStruct->max_bounds.width;
    selection *sel = &buf->primary;
    int nLines, mousePos, lineStart;
    int x, y, lineEnd;
    
    char *text;
    
    /* Save a copy of the whole text buffer as a backup, and for
       deriving changes */
    tw->text.dragOrigBuf = BufCreate();
    BufSetTabDistance(tw->text.dragOrigBuf, buf->tabDist);
    tw->text.dragOrigBuf->useTabs = buf->useTabs;
    text = BufGetAll(buf);
    BufSetAll(tw->text.dragOrigBuf, text);
    XtFree(text);
    if (sel->rectangular)
    	BufRectSelect(tw->text.dragOrigBuf, sel->start, sel->end, sel->rectStart,
    	    	sel->rectEnd);
    else
    	BufSelect(tw->text.dragOrigBuf, sel->start, sel->end);
 
    /* Record the mouse pointer offsets from the top left corner of the
       selection (the position where text will actually be inserted In dragging
       non-rectangular selections)  */
    if (sel->rectangular) {
    	tw->text.dragXOffset = tw->text.btnDownX + textD->horizOffset -
    	    	textD->left - sel->rectStart * fontWidth;
    } else {
        if (!TextDPositionToXY(textD, sel->start, &x, &y))
            x = BufCountDispChars(buf, TextDStartOfLine(textD, sel->start),
            	    sel->start) * fontWidth + textD->left -
            	    textD->horizOffset;
        tw->text.dragXOffset = tw->text.btnDownX - x;
    }
    mousePos = TextDXYToPosition(textD, tw->text.btnDownX, tw->text.btnDownY);
    nLines = BufCountLines(buf, sel->start, mousePos);
    tw->text.dragYOffset = nLines * fontHeight + (((tw->text.btnDownY -
    	    tw->text.marginHeight) % fontHeight) - fontHeight/2);
    tw->text.dragNLines = BufCountLines(buf, sel->start, sel->end);
    
    /* Record the current drag insert position and the information for
       undoing the fictional insert of the selection in its new position */
    tw->text.dragInsertPos = sel->start;
    tw->text.dragInserted = sel->end - sel->start;
    if (sel->rectangular) {
    	textBuffer *testBuf = BufCreate();
    	char *testText = BufGetRange(buf, sel->start, sel->end);
        BufSetTabDistance(testBuf, buf->tabDist);
        testBuf->useTabs = buf->useTabs;
    	BufSetAll(testBuf, testText);
    	XtFree(testText);
    	BufRemoveRect(testBuf, 0, sel->end - sel->start, sel->rectStart,
    	    	sel->rectEnd);
    	tw->text.dragDeleted = testBuf->length;
    	BufFree(testBuf);
    	tw->text.dragRectStart = sel->rectStart;
    } else {
    	tw->text.dragDeleted = 0;
    	tw->text.dragRectStart = 0;
    }
    tw->text.dragType = DRAG_MOVE;
    tw->text.dragSourceDeletePos = sel->start;
    tw->text.dragSourceInserted = tw->text.dragDeleted;
    tw->text.dragSourceDeleted = tw->text.dragInserted;
    
    /* For non-rectangular selections, fill in the rectangular information in
       the selection for overlay mode drags which are done rectangularly */
    if (!sel->rectangular) {
    	lineStart = BufStartOfLine(buf, sel->start);
    	if (tw->text.dragNLines == 0) {
    	    tw->text.dragOrigBuf->primary.rectStart =
    	    	    BufCountDispChars(buf, lineStart, sel->start);
    	    tw->text.dragOrigBuf->primary.rectEnd =
    	    	    BufCountDispChars(buf, lineStart, sel->end);
    	} else {
    	    lineEnd = BufGetCharacter(buf, sel->end - 1) == '\n' ? 
    	    	    sel->end - 1 : sel->end;
    	    findTextMargins(buf, lineStart, lineEnd,
    	    	    &tw->text.dragOrigBuf->primary.rectStart,
    	    	    &tw->text.dragOrigBuf->primary.rectEnd);
    	}
    }
    
    /* Set the drag state to announce an ongoing block-drag */
    tw->text.dragState = PRIMARY_BLOCK_DRAG;
    
    /* Call the callback announcing the start of a block drag */
    XtCallCallbacks((Widget)tw, textNdragStartCallback, (XtPointer)NULL);
}