Ejemplo n.º 1
0
static WindowInfo *findWindowOnDesktop(int tabbed, long currentDesktop)
{
    WindowInfo *window;
   
    if (tabbed == 0 || (tabbed == -1 && GetPrefOpenInTab() == 0)) {
        /* A new window is requested, unless we find an untitled unmodified
            document on the current desktop */
        for (window=WindowList; window!=NULL; window=window->next) {
            if (window->filenameSet || window->fileChanged ||
                    window->macroCmdData != NULL) {
                continue;
            }
            /* No check for top document here! */
            if (isLocatedOnDesktop(window, currentDesktop)) {
                return window;
            }
        }
    } else {
        /* Find a window on the current desktop to hold the new document */
        for (window=WindowList; window!=NULL; window=window->next) {
            /* Avoid unnecessary property access (server round-trip) */
            if (!IsTopDocument(window)) {
                continue;
            }
            if (isLocatedOnDesktop(window, currentDesktop)) {
                return window;
            }
        }
    }

    return NULL; /* No window found on current desktop -> create new window */
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
static void processServerCommandString(char *string)
{
    char *fullname, filename[MAXPATHLEN], pathname[MAXPATHLEN];
    char *doCommand, *geometry, *langMode, *inPtr;
    int editFlags, stringLen = strlen(string);
    int lineNum, createFlag, readFlag, iconicFlag, lastIconic = 0, tabbed = -1;
    int fileLen, doLen, lmLen, geomLen, charsRead, itemsRead;
    WindowInfo *window, *lastFile = NULL;
    long currentDesktop = QueryCurrentDesktop(TheDisplay, 
       RootWindow(TheDisplay, DefaultScreen(TheDisplay)));

    /* If the command string is empty, put up an empty, Untitled window
       (or just pop one up if it already exists) */
    if (string[0] == '\0') {
    	for (window=WindowList; window!=NULL; window=window->next)
    	    if (!window->filenameSet && !window->fileChanged &&
                isLocatedOnDesktop(window, currentDesktop))
    	    	break;
    	if (window == NULL) {
            EditNewFile(findWindowOnDesktop(tabbed, currentDesktop), NULL, 
                        False, NULL, NULL);
    	    CheckCloseDim();
    	} 
	else {
	    RaiseDocument(window);
            WmClientMsg(TheDisplay, XtWindow(window->shell),
                    "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
    	    XMapRaised(TheDisplay, XtWindow(window->shell));
    	}
	return;
    }

    /*
    ** Loop over all of the files in the command list
    */
    inPtr = string;
    while (TRUE) {
	
	if (*inPtr == '\0')
	    break;
	    
	/* Read a server command from the input string.  Header contains:
	   linenum createFlag fileLen doLen\n, followed by a filename and -do
	   command both followed by newlines.  This bit of code reads the
	   header, and converts the newlines following the filename and do
	   command to nulls to terminate the filename and doCommand strings */
	itemsRead = sscanf(inPtr, "%d %d %d %d %d %d %d %d %d%n", &lineNum,
		&readFlag, &createFlag, &iconicFlag, &tabbed, &fileLen,
		&doLen, &lmLen, &geomLen, &charsRead);
	if (itemsRead != 9)
    	    goto readError;
	inPtr += charsRead + 1;
	if (inPtr - string + fileLen > stringLen)
	    goto readError;
	fullname = inPtr;
	inPtr += fileLen;
	*inPtr++ = '\0';
	if (inPtr - string + doLen > stringLen)
	    goto readError;
	doCommand = inPtr;
	inPtr += doLen;
	*inPtr++ = '\0';
	if (inPtr - string + lmLen > stringLen)
	    goto readError;
	langMode = inPtr;
	inPtr += lmLen;
	*inPtr++ = '\0';
	if (inPtr - string + geomLen > stringLen)
	    goto readError;
	geometry = inPtr;
	inPtr += geomLen;
	*inPtr++ = '\0';
	
	/* An empty file name means: 
	 *   put up an empty, Untitled window, or use an existing one
	 *   choose a random window for executing the -do macro upon
	 */
	if (fileLen <= 0) {
    	    for (window=WindowList; window!=NULL; window=window->next)
    		if (!window->filenameSet && !window->fileChanged &&
                    isLocatedOnDesktop(window, currentDesktop))
    	    	    break;

    	    if (*doCommand == '\0') {
                if (window == NULL) {
    		    EditNewFile(findWindowOnDesktop(tabbed, currentDesktop), 
                                NULL, iconicFlag, lmLen==0?NULL:langMode, NULL);
    	        } else {
	            if (iconicFlag)
		    	RaiseDocument(window);
		    else
		    	RaiseDocumentWindow(window);
	        }
            } else {
                WindowInfo *win = WindowList;
		/* Starting a new command while another one is still running
		   in the same window is not possible (crashes). */
		while (win != NULL && win->macroCmdData != NULL) {
		    win = win->next;
		}
		
		if (!win) {
		    XBell(TheDisplay, 0);
		} else {
		    /* Raise before -do (macro could close window). */
	            if (iconicFlag)
		    	RaiseDocument(win);
		    else
		    	RaiseDocumentWindow(win);
		    DoMacro(win, doCommand, "-do macro");
		}
	    }
	    CheckCloseDim();
	    return;
	}
	
	/* Process the filename by looking for the files in an
	   existing window, or opening if they don't exist */
	editFlags = (readFlag ? PREF_READ_ONLY : 0) | CREATE |
		(createFlag ? SUPPRESS_CREATE_WARN : 0);
	if (ParseFilename(fullname, filename, pathname) != 0) {
	   fprintf(stderr, "NEdit: invalid file name\n");
           deleteFileClosedProperty2(filename, pathname);
	   break;
	}

    	window = FindWindowWithFile(filename, pathname);
    	if (window == NULL) {
	    /* Files are opened in background to improve opening speed
	       by defering certain time  consuiming task such as syntax
	       highlighting. At the end of the file-opening loop, the 
	       last file opened will be raised to restore those deferred
	       items. The current file may also be raised if there're
	       macros to execute on. */
	    window = EditExistingFile(findWindowOnDesktop(tabbed, currentDesktop),
		    filename, pathname, editFlags, geometry, iconicFlag, 
		    lmLen == 0 ? NULL : langMode, 
		    tabbed == -1? GetPrefOpenInTab() : tabbed, True);

    	    if (window) {
	    	CleanUpTabBarExposeQueue(window);
		if (lastFile && window->shell != lastFile->shell) {
		    CleanUpTabBarExposeQueue(lastFile);
		    RaiseDocument(lastFile);
		}
	    }
	    
	}
	
	/* Do the actions requested (note DoMacro is last, since the do
	   command can do anything, including closing the window!) */
	if (window != NULL) {
            deleteFileOpenProperty(window);
            getFileClosedProperty(window);

	    if (lineNum > 0)
		SelectNumberedLine(window, lineNum);

	    if (*doCommand != '\0') {
		RaiseDocument(window);

                if (!iconicFlag) {
                    WmClientMsg(TheDisplay, XtWindow(window->shell),
                            "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
		    XMapRaised(TheDisplay, XtWindow(window->shell));
                }

		/* Starting a new command while another one is still running
		   in the same window is not possible (crashes). */
		if (window->macroCmdData != NULL) {
		    XBell(TheDisplay, 0);
		} else {
		    DoMacro(window, doCommand, "-do macro");
		    /* in case window is closed by macro functions
		       such as close() or detach_document() */
		    if (!IsValidWindow(window))
		    	window = NULL;
		    if (lastFile && !IsValidWindow(lastFile))
		    	lastFile = NULL;
		}
	    }
	    
	    /* register the last file opened for later use */
	    if (window) {
	    	lastFile = window;
		lastIconic = iconicFlag;
	    }
	} else {
            deleteFileOpenProperty2(filename, pathname);
            deleteFileClosedProperty2(filename, pathname);
        }
    }
    
    /* Raise the last file opened */
    if (lastFile) {
	CleanUpTabBarExposeQueue(lastFile);
	if (lastIconic)
	    RaiseDocument(lastFile);
	else
	    RaiseDocumentWindow(lastFile);
	CheckCloseDim();
    }
    return;

readError:
    fprintf(stderr, "NEdit: error processing server request\n");
    return;
}
Ejemplo n.º 4
0
static void fileCB(Widget widget, WindowInfo *window, Atom *sel,
    	Atom *type, char *value, int *length, int *format)
{
    char nameText[MAXPATHLEN], includeName[MAXPATHLEN];
    char filename[MAXPATHLEN], pathname[MAXPATHLEN];
    char *inPtr, *outPtr;
#ifdef VMS
#ifndef __DECC
    static char includeDir[] = "sys$library:";
#else
    static char includeDir[] = "decc$library_include:";
#endif
#else
    static char includeDir[] = "/usr/include/";
#endif /* VMS */
    
    /* get the string, or skip if we can't get the selection data, or it's
       obviously not a file name */
    if (*type == XT_CONVERT_FAIL || value == NULL) {
    	XBell(TheDisplay, 0);
	return;
    }
    if (*length > MAXPATHLEN || *length == 0) {
    	XBell(TheDisplay, 0);
	XtFree(value);
	return;
    }
    /* should be of type text??? */
    if (*format != 8) {
    	fprintf(stderr, "NEdit: Can't handle non 8-bit text\n");
    	XBell(TheDisplay, 0);
	XtFree(value);
	return;
    }
    strncpy(nameText, value, *length);
    XtFree(value);
    nameText[*length] = '\0';
    
    /* extract name from #include syntax */
    if (sscanf(nameText, "#include \"%[^\"]\"", includeName) == 1)
    	strcpy(nameText, includeName);
    else if (sscanf(nameText, "#include <%[^<>]>", includeName) == 1)
    	sprintf(nameText, "%s%s", includeDir, includeName);
    
    /* strip whitespace from name */
    for (inPtr=nameText, outPtr=nameText; *inPtr!='\0'; inPtr++)
    	if (*inPtr != ' ' && *inPtr != '\t' && *inPtr != '\n')
    	    *outPtr++ = *inPtr;
    *outPtr = '\0';

#ifdef VMS
    /* If path name is relative, make it refer to current window's directory */
    if ((strchr(nameText, ':') == NULL) && (strlen(nameText) > 1) &&
      	    !((nameText[0] == '[') && (nameText[1] != '-') &&
	      (nameText[1] != '.'))) {
	strcpy(filename, window->path);
	strcat(filename, nameText);
	strcpy(nameText, filename);
    }
#else
    /* Process ~ characters in name */
    ExpandTilde(nameText);
        
    /* If path name is relative, make it refer to current window's directory */
    if (nameText[0] != '/') {
	strcpy(filename, window->path);
	strcat(filename, nameText);
	strcpy(nameText, filename);
    }
#endif
    
    /* Expand wildcards in file name.
       Some older systems don't have the glob subroutine for expanding file
       names, in these cases, either don't expand names, or try to use the
       Motif internal parsing routine _XmOSGetDirEntries, which is not
       guranteed to be available, but in practice is there and does work. */
#if defined(DONT_HAVE_GLOB) || defined(VMS)
    /* Open the file */
    if (ParseFilename(nameText, filename, pathname) != 0) {
        XBell(TheDisplay, 0);
	return;
    }	
    EditExistingFile(window, filename, 
            pathname, 0, NULL, False, NULL, GetPrefOpenInTab(), False);
#elif defined(USE_MOTIF_GLOB)
    { char **nameList = NULL;
      int i, nFiles = 0, maxFiles = 30;

      if (ParseFilename(nameText, filename, pathname) != 0) {
           XBell(TheDisplay, 0);
	   return;
      }
      _XmOSGetDirEntries(pathname, filename, XmFILE_ANY_TYPE, False, True,
	      &nameList, &nFiles, &maxFiles);
      for (i=0; i<nFiles; i++) {
	  if (ParseFilename(nameList[i], filename, pathname) != 0) {
	      XBell(TheDisplay, 0);
	  }
        else {
    	      EditExistingFile(window, filename, pathname, 0, 
	              NULL, False, NULL, GetPrefOpenInTab(), False);
	  }
      }
      for (i=0; i<nFiles; i++) {
	   XtFree(nameList[i]);
	}
      XtFree((char *)nameList);
    }
#else
    { glob_t globbuf;
      int i;

      glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
      for (i=0; i<(int)globbuf.gl_pathc; i++) {
	  if (ParseFilename(globbuf.gl_pathv[i], filename, pathname) != 0)
	      XBell(TheDisplay, 0);
	  else
    	      EditExistingFile(GetPrefOpenInTab()? window : NULL, 
	              filename, pathname, 0, NULL, False, NULL, 
		      GetPrefOpenInTab(), False);
      }
      globfree(&globbuf);
    }
#endif
    CheckCloseDim();
}