/* ** Filter the current selection through shell command "command". The selection ** is removed, and replaced by the output from the command execution. Failed ** command status and output to stderr are presented in dialog form. */ void FilterSelection(WindowInfo *window, const char *command, int fromMacro) { int left, right, textLen; char *text; /* Can't do two shell commands at once in the same window */ if (window->shellCmdData != NULL) { XBell(TheDisplay, 0); return; } /* Get the selection and the range in character positions that it occupies. Beep and return if no selection */ text = BufGetSelectionText(window->buffer); if (*text == '\0') { XtFree(text); XBell(TheDisplay, 0); return; } textLen = strlen(text); BufUnsubstituteNullChars(text, window->buffer); left = window->buffer->primary.start; right = window->buffer->primary.end; /* Issue the command and collect its output */ issueCommand(window, command, text, textLen, ACCUMULATE | ERROR_DIALOGS | REPLACE_SELECTION, window->lastFocus, left, right, fromMacro); }
/* ** Getting the current selection by making the request, and then blocking ** (processing events) while waiting for a reply. On failure (timeout or ** bad format) returns NULL, otherwise returns the contents of the selection. */ char *GetAnySelection(WindowInfo *window) { static char waitingMarker[1] = ""; char *selText = waitingMarker; XEvent nextEvent; /* If the selection is in the window's own buffer get it from there, but substitute null characters as if it were an external selection */ if (window->buffer->primary.selected) { selText = BufGetSelectionText(window->buffer); BufUnsubstituteNullChars(selText, window->buffer); return selText; } /* Request the selection value to be delivered to getAnySelectionCB */ XtGetSelectionValue(window->textArea, XA_PRIMARY, XA_STRING, (XtSelectionCallbackProc)getAnySelectionCB, &selText, XtLastTimestampProcessed(XtDisplay(window->textArea))); /* Wait for the value to appear */ while (selText == waitingMarker) { XtAppNextEvent(XtWidgetToApplicationContext(window->textArea), &nextEvent); ServerDispatchEvent(&nextEvent); } return selText; }
/* ** Execute the line of text where the the insertion cursor is positioned ** as a shell command. */ void ExecCursorLine(WindowInfo *window, int fromMacro) { char *cmdText; int left, right, insertPos; char *subsCommand, fullName[MAXPATHLEN]; int pos, line, column; char lineNumber[11]; /* Can't do two shell commands at once in the same window */ if (window->shellCmdData != NULL) { XBell(TheDisplay, 0); return; } /* get all of the text on the line with the insert position */ pos = TextGetCursorPos(window->lastFocus); if (!GetSimpleSelection(window->buffer, &left, &right)) { left = right = pos; left = BufStartOfLine(window->buffer, left); right = BufEndOfLine(window->buffer, right); insertPos = right; } else insertPos = BufEndOfLine(window->buffer, right); cmdText = BufGetRange(window->buffer, left, right); BufUnsubstituteNullChars(cmdText, window->buffer); /* insert a newline after the entire line */ BufInsert(window->buffer, insertPos, "\n"); /* Substitute the current file name for % and the current line number for # in the shell command */ strcpy(fullName, window->path); strcat(fullName, window->filename); TextPosToLineAndCol(window->lastFocus, pos, &line, &column); sprintf(lineNumber, "%d", line); subsCommand = shellCommandSubstitutes(cmdText, 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; } /* issue the command */ issueCommand(window, subsCommand, NULL, 0, 0, window->lastFocus, insertPos+1, insertPos+1, fromMacro); free(subsCommand); XtFree(cmdText); }
/* ** Copy the primary selection to the clipboard */ void CopyToClipboard(Ne_Text_Editor* textD, double time) { long itemID = 0; /* Get the selected text, if there's no selection, do nothing */ char* text = BufGetSelectionText(textD->buffer); if (*text == '\0') { free__(text); return; } /* If the string contained ascii-nul characters, something else was substituted in the buffer. Put the nulls back */ int length = strlen(text); BufUnsubstituteNullChars(text, textD->buffer); // Copy to the clipboard Fl::copy(text, length, 1); }
/* ** 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); }