393 lines
12 KiB
C
393 lines
12 KiB
C
/*
|
|
* 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
|
|
*/
|
|
/* $XConsortium: fileIo.c /main/4 1996/10/04 17:24:28 drk $ */
|
|
/**********************************<+>*************************************
|
|
***************************************************************************
|
|
**
|
|
** File: fileIo.c
|
|
**
|
|
** Project: DT dtpad, a memo maker type editor based on the Dt Editor
|
|
** widget.
|
|
**
|
|
** Description:
|
|
** -----------
|
|
**
|
|
*******************************************************************
|
|
** (c) Copyright Hewlett-Packard Company, 1991, 1992. All rights are
|
|
** reserved. Copying or other reproduction of this program
|
|
** except for archival purposes is prohibited without prior
|
|
** written consent of Hewlett-Packard Company.
|
|
********************************************************************
|
|
**
|
|
********************************************************************
|
|
** (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
** (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
** (c) Copyright 1993, 1994 Novell, Inc.
|
|
********************************************************************
|
|
**
|
|
** ToDo: roll in fixes for 10.0 ivepad
|
|
**
|
|
**
|
|
**************************************************************************
|
|
**********************************<+>*************************************/
|
|
#include "dtpad.h"
|
|
#include <Xm/TextP.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/LabelG.h>
|
|
#include <Dt/HourGlass.h>
|
|
|
|
|
|
/************************************************************************
|
|
* LoadFile - Opens the specified file and loads its contents to the
|
|
* DtEditor widget.
|
|
*
|
|
* The filename is specified either by pPad->fileStuff.fileName or
|
|
* the 'include' argument. If the filename is specified via include,
|
|
* the file is inserted at the current cursor location. In both
|
|
* instances, the filename is assumed to be relative to the local host
|
|
* where dtpad is running.
|
|
*
|
|
************************************************************************/
|
|
/* [SuG 5/18/95] Done
|
|
The NOT_SAMPLE warnings/errors need to be added to the message
|
|
catalog. Removed ifdefs.*/
|
|
|
|
void
|
|
LoadFile(
|
|
Editor *pPad,
|
|
char *include)
|
|
{
|
|
char * localName;
|
|
DtEditorErrorCode errorCode;
|
|
DtEditorContentRec contentRec;
|
|
Boolean fileLoaded = False;
|
|
Boolean fileLoadError = False;
|
|
|
|
|
|
if (include != (char *)NULL) {
|
|
localName = include;
|
|
} else {
|
|
localName = pPad->fileStuff.fileName;
|
|
pPad->fileStuff.readOnly = False;
|
|
}
|
|
|
|
if (localName && *localName) {
|
|
/* try to load the file to the Dt Editor widget */
|
|
_DtTurnOnHourGlass(pPad->app_shell);
|
|
XSync(XtDisplay(pPad->editor), False);
|
|
if (include != (char *) NULL) {
|
|
errorCode = DtEditorInsertFromFile(
|
|
pPad->editor,
|
|
localName);
|
|
} else {
|
|
pPad->fileStuff.fileExists = True;
|
|
errorCode = DtEditorSetContentsFromFile(
|
|
pPad->editor,
|
|
localName);
|
|
}
|
|
_DtTurnOffHourGlass(pPad->app_shell);
|
|
switch (errorCode) {
|
|
case DtEDITOR_NO_ERRORS: /* file is read/writeable */
|
|
fileLoaded = True;
|
|
break;
|
|
case DtEDITOR_READ_ONLY_FILE:
|
|
fileLoaded = True;
|
|
if (include == (char *) NULL) {
|
|
pPad->fileStuff.readOnly = True;
|
|
if (pPad->xrdb.readOnlyWarning &&
|
|
! pPad->xrdb.statusLine &&
|
|
! pPad->xrdb.viewOnly) {
|
|
Warning(pPad, (char *) GETMESSAGE(6, 1,
|
|
"This file has been opened for reading only."),
|
|
XmDIALOG_WARNING);
|
|
}
|
|
}
|
|
break;
|
|
case DtEDITOR_NONEXISTENT_FILE:
|
|
if (include != (char *) NULL ) {
|
|
Warning(pPad, (char *) GETMESSAGE(6, 2,
|
|
"This file does not exist."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
} else if (pPad->xrdb.viewOnly) {
|
|
Warning(pPad, (char *) GETMESSAGE(6, 2,
|
|
"This file does not exist."),
|
|
XmDIALOG_ERROR);
|
|
} else if (pPad->xrdb.missingFileWarning) {
|
|
Warning(pPad, (char *) GETMESSAGE(6, 2,
|
|
"This file does not exist."),
|
|
XmDIALOG_WARNING);
|
|
}
|
|
break;
|
|
case DtEDITOR_DIRECTORY:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 3,
|
|
"Unable to edit a Directory."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
case DtEDITOR_CHAR_SPECIAL_FILE:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 4,
|
|
"Unable to edit a character special device file."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
case DtEDITOR_BLOCK_MODE_FILE:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 5,
|
|
"Unable to edit a block mode device file."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
case DtEDITOR_NULLS_REMOVED:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 6,
|
|
"Embedded Nulls stripped from file."),
|
|
XmDIALOG_WARNING);
|
|
fileLoaded = True;
|
|
break;
|
|
case DtEDITOR_INSUFFICIENT_MEMORY:
|
|
Warning(pPad, (char*) GETMESSAGE(6, 7,
|
|
"Unable to load file (insufficient memory)."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
case DtEDITOR_NO_FILE_ACCESS:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 8,
|
|
"Unable to access file (can't determine its status)."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
case DtEDITOR_UNREADABLE_FILE:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 9,
|
|
"Unable to read from the file (probably no read permission)."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
default:
|
|
Warning(pPad, (char *) GETMESSAGE(6, 12,
|
|
"Unable to read from the file (unknown reason)."),
|
|
XmDIALOG_ERROR);
|
|
fileLoadError = True;
|
|
break;
|
|
} /* switch (errorCode) */
|
|
} /* file name specified */
|
|
|
|
if (include != (char *)NULL)
|
|
return;
|
|
|
|
/*
|
|
* We only get this far if the current file was to be changed
|
|
* (i.e. the file was not included)
|
|
*/
|
|
SetStatusLineMsg(pPad); /* set readOnly/viewOnly in status line msg */
|
|
|
|
if (fileLoaded) {
|
|
pPad->fileStuff.fileExists = True;
|
|
} else {
|
|
pPad->fileStuff.fileExists = False;
|
|
|
|
/* null out Editor widget */
|
|
contentRec.type = DtEDITOR_TEXT;
|
|
contentRec.value.string = "";
|
|
errorCode = DtEditorSetContents(pPad->editor, &contentRec);
|
|
if (errorCode != DtEDITOR_NO_ERRORS)
|
|
Warning(pPad,"Internal Error: Unable to NULL Editor Widget.",XmDIALOG_ERROR);
|
|
|
|
/* clear stale file stuff */
|
|
if (fileLoadError) {
|
|
if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName)
|
|
XtFree(pPad->fileStuff.fileName);
|
|
pPad->fileStuff.fileName = NULL;
|
|
ChangeMainWindowTitle(pPad);
|
|
return;
|
|
}
|
|
|
|
/* set the pathDir and fileName */
|
|
if (pPad->fileStuff.fileName && *pPad->fileStuff.fileName) {
|
|
char *lastSlash;
|
|
|
|
strcpy(pPad->fileStuff.pathDir, pPad->fileStuff.fileName);
|
|
if ((lastSlash = MbStrrchr(pPad->fileStuff.pathDir, '/')) !=
|
|
(char *)NULL) {
|
|
*(lastSlash + 1) = (char)'\0';
|
|
}
|
|
|
|
lastSlash = MbStrrchr(pPad->fileStuff.fileName, '/');
|
|
if (lastSlash != (char *)NULL) {
|
|
lastSlash++;
|
|
} else {
|
|
lastSlash = pPad->fileStuff.fileName;
|
|
}
|
|
if (*lastSlash == (char)'-' || *lastSlash == (char)'*') {
|
|
XtFree(pPad->fileStuff.fileName);
|
|
pPad->fileStuff.fileName = (char *)NULL;
|
|
}
|
|
}
|
|
} /* ! fileLoaded */
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* GetTempFile - generates a file name for a temporary file that can be
|
|
* used for writing.
|
|
************************************************************************/
|
|
char *
|
|
GetTempFile(void)
|
|
{
|
|
char *tempname = (char *)XtMalloc(L_tmpnam); /* Temporary file name. */
|
|
FILE *tfp;
|
|
|
|
(void)tmpnam(tempname);
|
|
if ((tfp = fopen(tempname, "w")) == NULL)
|
|
{
|
|
pid_t pid;
|
|
/*
|
|
* If tmpnam fails, then try to create our own temp name.
|
|
* Try a couple of different names if necessary.
|
|
*/
|
|
XtFree(tempname);
|
|
tempname = XtMalloc(256);
|
|
pid = getpid();
|
|
sprintf(tempname, "/usr/tmp/editor%ld", (long)pid);
|
|
if ((tfp = fopen(tempname, "w")) == NULL)
|
|
{
|
|
sprintf(tempname, "/tmp/editor%ld", (long)pid);
|
|
if ((tfp = fopen(tempname, "w")) == NULL)
|
|
{
|
|
XtFree(tempname);
|
|
return (char *)NULL;
|
|
}
|
|
}
|
|
}
|
|
fclose(tfp);
|
|
return tempname;
|
|
}
|
|
|
|
|
|
extern Editor *pPadList; /* declared/set in main.c */
|
|
|
|
|
|
/************************************************************************
|
|
* AddPound - add a "#" character to the beginning of the base name of
|
|
* the file name passed in the nameBuf parameter. A pointer to the
|
|
* new name is returned. The name is constructed in a static buffer.
|
|
* If nameBuf is empty, it returns the file name "#UNTITLED#".
|
|
************************************************************************/
|
|
static char *
|
|
AddPound(
|
|
char *nameBuf)
|
|
{
|
|
char tempBuf[512];
|
|
static char returnBuf[512];
|
|
|
|
if (nameBuf != (char *)NULL && nameBuf[0] != (char) '\0') {
|
|
char *baseName;
|
|
strcpy(tempBuf, nameBuf);
|
|
baseName = MbStrrchr(tempBuf, '/');
|
|
if (baseName != (char *)NULL) {
|
|
strncpy(returnBuf, tempBuf, (baseName - tempBuf) + 1);
|
|
returnBuf[(baseName - tempBuf) + 1] = (char)'\0';
|
|
baseName++;
|
|
strcat(returnBuf, "#");
|
|
strcat(returnBuf, baseName);
|
|
if (returnBuf[strlen(returnBuf) - 1] != (char)'#')
|
|
strcat(returnBuf, "#");
|
|
} else {
|
|
snprintf(returnBuf, sizeof(returnBuf), "#%s", tempBuf);
|
|
if(strlen(returnBuf) && returnBuf[strlen(returnBuf) - 1] != (char)'#')
|
|
strcat(returnBuf, "#");
|
|
}
|
|
} else {
|
|
sprintf(returnBuf, "#%s#", GETMESSAGE(5, 21, "UNTITLED"));
|
|
}
|
|
return returnBuf;
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* PanicSave - immediately saves the text for each edit session handled
|
|
* by the text editor to #[#]<filename>.
|
|
************************************************************************/
|
|
void
|
|
PanicSave(void)
|
|
{
|
|
Editor *pPad;
|
|
struct stat statbuf; /* Information on a file. */
|
|
Boolean addNewLines;
|
|
DtEditorErrorCode errorCode;
|
|
|
|
for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
|
|
char *fileName = pPad->fileStuff.fileName;
|
|
if (pPad->inUse != True || pPad->editor == NULL ||
|
|
(! DtEditorCheckForUnsavedChanges(pPad->editor)))
|
|
continue;
|
|
/* -----> Try to cook up a name for a file that doesn't already exist */
|
|
fileName = AddPound(pPad->fileStuff.fileName);
|
|
if (stat(fileName, &statbuf) == 0) {
|
|
fileName = AddPound(fileName);
|
|
if (stat(fileName, &statbuf) == 0) {
|
|
fileName = AddPound(fileName);
|
|
if (stat(fileName, &statbuf) == 0) {
|
|
/* Give up. We've tried enough names. The user loses. */
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
addNewLines = pPad->xrdb.wordWrap == True &&
|
|
pPad->fileStuff.saveWithNewlines == True;
|
|
errorCode = DtEditorSaveContentsToFile(
|
|
pPad->editor,
|
|
fileName,
|
|
False, /* don't overwrite existing file */
|
|
addNewLines, /* replace soft line feeds? */
|
|
False); /* don't mark contents as saved */
|
|
|
|
/* don't really care about errorCode since we're in a hurry and
|
|
* can't do anything about it anyway */
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SetStatusLineMsg - sets the message (XmTextField) portion of the
|
|
* DtEditor widget's status line based on whether the pad is in
|
|
* viewOnly mode or the file being edited/displayed is readOnly.
|
|
************************************************************************/
|
|
/* ARGSUSED */
|
|
void
|
|
SetStatusLineMsg(
|
|
Editor *pPad)
|
|
{
|
|
char *message="";
|
|
|
|
if (pPad->xrdb.viewOnly) {
|
|
message = (char *) GETMESSAGE(6, 10, "View Only");
|
|
} else if (pPad->fileStuff.readOnly) {
|
|
message = (char *) GETMESSAGE(6, 11, "Read Only");
|
|
}
|
|
|
|
XmTextFieldSetString(pPad->statusLineMsg, message);
|
|
}
|