supersax
asked on
Saving text from 4 fields to a file
I wrote a small programm where the user inputs some text inside 4 different fields.
How can I save this data to a file in way that it may be reopened and displayed inside the 4 fields? I mean in the same order in which it was inputted.
I'm using this struct for the four text fields:
typedef struct
{
TEHandle inputFieldAuthorHdl;
TEHandle inputFieldTitleHdl;
TEHandle inputFieldPublisherHdl;
TEHandle inputFieldYearHdl;
} DocRec, **DocRecHandle;
Actually I'm able to save it, but when I reopen it, all the text appears in the first field. Even if I open it from Simple Text, the text appears like a continuos line.
How can I save this data to a file in way that it may be reopened and displayed inside the 4 fields? I mean in the same order in which it was inputted.
I'm using this struct for the four text fields:
typedef struct
{
TEHandle inputFieldAuthorHdl;
TEHandle inputFieldTitleHdl;
TEHandle inputFieldPublisherHdl;
TEHandle inputFieldYearHdl;
} DocRec, **DocRecHandle;
Actually I'm able to save it, but when I reopen it, all the text appears in the first field. Even if I open it from Simple Text, the text appears like a continuos line.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This code demonstrates how the proposed solution works.
static void Initialize(void)
{
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
}
static void WriteTEH(TEHandle teH,long lng, FILE *outFile)
{
unsigned char state;
state = HGetState((**teH).hText);
HLock((**teH).hText);
fwrite(*(**teH).hText,size of(char),l ng,outFile );
HSetState((**teH).hText,st ate);
}
static void ReadTEH(TEHandle teH,long lng, FILE *inFile)
{
unsigned char state;
state = HGetState((**teH).hText);
HLock((**teH).hText);
fread(*(**teH).hText,sizeo f(char),ln g,inFile);
HSetState((**teH).hText,st ate);
}
int main(void)
{
TEHandle te1,te2;
Rect destRect,viewRect;
long size1,size2;
FILE *outFile,*inFile;
char text1[] = "this is text 1";
char text2[] = "this is text 2 but it is longer";
Initialize();
SetRect(&destRect,0,0,100, 100);
SetRect(&viewRect,0,0,100, 100);
/* initialize - this is replaced with whatever code you use to get your TEHandles */
te1 = TENew(&destRect,&viewRect) ;
te2 = TENew(&destRect,&viewRect) ;
TEInsert(text1,strlen(text 1),te1);
TEInsert(text2,strlen(text 2),te2);
/* write file */
outFile = fopen("test.out","w");
if (0==outFile) DebugStr("\p unable to open output file");
size1 = GetHandleSize((**te1).hTex t);
size2 = GetHandleSize((**te2).hTex t);
fwrite(&size1,sizeof(long) ,1,outFile );
fwrite(&size2,sizeof(long) ,2,outFile );
WriteTEH(te1,size1,outFile );
WriteTEH(te2,size2,outFile );
fclose(outFile);
/* clear a byte of the text so we can see it is read properly */
**(**te1).hText = 0;
**(**te2).hText = 0;
size1 = size2 = 0;
/* read file */
inFile = fopen("test.out","r");
if (0==inFile) DebugStr("\p unable to open input file");
fread(&size1,sizeof(long), 1,inFile);
fread(&size2,sizeof(long), 2,inFile);
ReadTEH(te1,size1,inFile);
ReadTEH(te2,size2,inFile);
}
static void Initialize(void)
{
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
}
static void WriteTEH(TEHandle teH,long lng, FILE *outFile)
{
unsigned char state;
state = HGetState((**teH).hText);
HLock((**teH).hText);
fwrite(*(**teH).hText,size
HSetState((**teH).hText,st
}
static void ReadTEH(TEHandle teH,long lng, FILE *inFile)
{
unsigned char state;
state = HGetState((**teH).hText);
HLock((**teH).hText);
fread(*(**teH).hText,sizeo
HSetState((**teH).hText,st
}
int main(void)
{
TEHandle te1,te2;
Rect destRect,viewRect;
long size1,size2;
FILE *outFile,*inFile;
char text1[] = "this is text 1";
char text2[] = "this is text 2 but it is longer";
Initialize();
SetRect(&destRect,0,0,100,
SetRect(&viewRect,0,0,100,
/* initialize - this is replaced with whatever code you use to get your TEHandles */
te1 = TENew(&destRect,&viewRect)
te2 = TENew(&destRect,&viewRect)
TEInsert(text1,strlen(text
TEInsert(text2,strlen(text
/* write file */
outFile = fopen("test.out","w");
if (0==outFile) DebugStr("\p unable to open output file");
size1 = GetHandleSize((**te1).hTex
size2 = GetHandleSize((**te2).hTex
fwrite(&size1,sizeof(long)
fwrite(&size2,sizeof(long)
WriteTEH(te1,size1,outFile
WriteTEH(te2,size2,outFile
fclose(outFile);
/* clear a byte of the text so we can see it is read properly */
**(**te1).hText = 0;
**(**te2).hText = 0;
size1 = size2 = 0;
/* read file */
inFile = fopen("test.out","r");
if (0==inFile) DebugStr("\p unable to open input file");
fread(&size1,sizeof(long),
fread(&size2,sizeof(long),
ReadTEH(te1,size1,inFile);
ReadTEH(te2,size2,inFile);
}
ASKER
Saving seems working. May be I have to convert the TEHandles to strings before saving.
I try also to use the following code. I can't make it work well to read the file. Also, how do you display the content to the file from the TEHandle back to editable text?
// ???????????????????????? doSaveAsFile
void doSaveAsFile(TEHandle fieldOneHdl, TEHandle fieldTwoHdl)
{
StandardFileReply fileReply;
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldOneLength, fieldTwoLength;
DocRecHandle docRecHdl;
StandardPutFile("\pSave as:","\pUntitled",&fileRep ly);
if(fileReply.sfGood)
{
windowPtr = FrontWindow();
SetWTitle(windowPtr,fileRe ply.sfFile .name);
if(!(fileReply.sfReplacing ))
FSpCreate(&fileReply.sfFil e,'????',' TEXT',file Reply.sfSc ript);
FSpOpenDF(&fileReply.sfFil e,fsCurPer m,&fileRef Num);
fieldOneLength = (*(*docRecHdl)->inputField OneHdl)->t eLength;
fieldTwoLength = (*(*docRecHdl)->inputField TwoHdl)->t eLength;
fieldOneHdl = (*docRecHdl)->inputFieldOn eHdl;
fieldTwoHdl = (*docRecHdl)->inputFieldTw oHdl;
FSWrite(fileRefNum,&fieldO neLength,* fieldOneHd l);
FSWrite(fileRefNum,&fieldT woLength,* fieldTwoHd l);
FSClose(fileRefNum);
}
}
???????????? doOpenCommand
void doOpenCommand(void)
{
StandardFileReply fileReply;
SFTypeList fileTypes;
fileTypes[0] = 'TEXT';
StandardGetFile(NULL,1,fil eTypes,&fi leReply);
if(fileReply.sfGood)
doOpenFile(fileReply.sfFil e);
}
// ?????????? doOpenFile
void doOpenFile(FSSpec fileSpec)
{
WindowPtr windowPtr;
DocRecHandle docRecHdl;
TEHandle fieldOneHdl, fieldTwoHdl;
SInt16 fileRefNum;
SInt32 fieldOneLength, fieldTwoLength; //textLength
Handle textBuffer1,textBuffer2;
if((windowPtr = doNewDocWindow()) == NULL)
return;
docRecHdl = (DocRecHandle) (GetWRefCon(windowPtr));;
fieldOneHdl = (*docRecHdl)->inputFieldOn eHdl;
fieldTwoHdl = (*docRecHdl)->inputFieldTw oHdl;
SetWTitle(windowPtr,fileSp ec.name);
FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);
SetFPos(fileRefNum,fsFromS tart,0);
GetEOF(fileRefNum,&fieldOn eLength);
GetEOF(fileRefNum,&fieldTw oLength);
if(fieldOneLength > 32767 )
fieldOneLength = 32767;
textBuffer1 = NewHandle((Size) fieldOneLength);
textBuffer2 = NewHandle((Size) fieldTwoLength);
FSRead(fileRefNum,&fieldOn eLength,*t extBuffer1 );
FSRead(fileRefNum,&fieldTw oLength,*t extBuffer2 );
MoveHHi(textBuffer1); MoveHHi(textBuffer2);
HLock(textBuffer1); HLock(textBuffer2);
TESetText(*textBuffer1, fieldOneLength, fieldOneHdl);
TESetText(*textBuffer2, fieldTwoLength, fieldTwoHdl);
HUnlock(textBuffer1); HUnlock(textBuffer2);
DisposeHandle(textBuffer1) ; DisposeHandle(textBuffer2) ;
FSClose(fileRefNum);
(*fieldOneHdl)->selStart = 0; (*fieldTwoHdl)->selStart = 0;
(*fieldOneHdl)->selEnd = 0; (*fieldTwoHdl)->selEnd = 0;
ShowWindow(windowPtr);
}
I try also to use the following code. I can't make it work well to read the file. Also, how do you display the content to the file from the TEHandle back to editable text?
// ???????????????????????? doSaveAsFile
void doSaveAsFile(TEHandle fieldOneHdl, TEHandle fieldTwoHdl)
{
StandardFileReply fileReply;
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldOneLength, fieldTwoLength;
DocRecHandle docRecHdl;
StandardPutFile("\pSave as:","\pUntitled",&fileRep
if(fileReply.sfGood)
{
windowPtr = FrontWindow();
SetWTitle(windowPtr,fileRe
if(!(fileReply.sfReplacing
FSpCreate(&fileReply.sfFil
FSpOpenDF(&fileReply.sfFil
fieldOneLength = (*(*docRecHdl)->inputField
fieldTwoLength = (*(*docRecHdl)->inputField
fieldOneHdl = (*docRecHdl)->inputFieldOn
fieldTwoHdl = (*docRecHdl)->inputFieldTw
FSWrite(fileRefNum,&fieldO
FSWrite(fileRefNum,&fieldT
FSClose(fileRefNum);
}
}
???????????? doOpenCommand
void doOpenCommand(void)
{
StandardFileReply fileReply;
SFTypeList fileTypes;
fileTypes[0] = 'TEXT';
StandardGetFile(NULL,1,fil
if(fileReply.sfGood)
doOpenFile(fileReply.sfFil
}
// ?????????? doOpenFile
void doOpenFile(FSSpec fileSpec)
{
WindowPtr windowPtr;
DocRecHandle docRecHdl;
TEHandle fieldOneHdl, fieldTwoHdl;
SInt16 fileRefNum;
SInt32 fieldOneLength, fieldTwoLength; //textLength
Handle textBuffer1,textBuffer2;
if((windowPtr = doNewDocWindow()) == NULL)
return;
docRecHdl = (DocRecHandle) (GetWRefCon(windowPtr));;
fieldOneHdl = (*docRecHdl)->inputFieldOn
fieldTwoHdl = (*docRecHdl)->inputFieldTw
SetWTitle(windowPtr,fileSp
FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);
SetFPos(fileRefNum,fsFromS
GetEOF(fileRefNum,&fieldOn
GetEOF(fileRefNum,&fieldTw
if(fieldOneLength > 32767 )
fieldOneLength = 32767;
textBuffer1 = NewHandle((Size) fieldOneLength);
textBuffer2 = NewHandle((Size) fieldTwoLength);
FSRead(fileRefNum,&fieldOn
FSRead(fileRefNum,&fieldTw
MoveHHi(textBuffer1); MoveHHi(textBuffer2);
HLock(textBuffer1); HLock(textBuffer2);
TESetText(*textBuffer1, fieldOneLength, fieldOneHdl);
TESetText(*textBuffer2, fieldTwoLength, fieldTwoHdl);
HUnlock(textBuffer1); HUnlock(textBuffer2);
DisposeHandle(textBuffer1)
FSClose(fileRefNum);
(*fieldOneHdl)->selStart = 0; (*fieldTwoHdl)->selStart = 0;
(*fieldOneHdl)->selEnd = 0; (*fieldTwoHdl)->selEnd = 0;
ShowWindow(windowPtr);
}
Your read code doesn't work because you don't appear to be writing the text field lengths to the file. You need to include something like this before you write the strings:
bytesToWrite = sizeof(SInt32)
FSWrite(fileRefNum,&bytesT oWrite,&fi eldOneLeng th);
Then you need to read the length back:
bytesToRead = sizeof(SInt32)
FSRead(fileRefNum,&bytesTo Read,&fiel dOneLength );
Then you can read the text:
bytesToRead = fieldOneLength;
FSRead(fileRefNum,&bytesTo Read,*text Buffer1);
To put the text read from the file back into your TEHandle, use TESetText (as you are doing):
TESetText(*textBuffer1,fie ldOneLengt h,fieldOne Hdl);
bytesToWrite = sizeof(SInt32)
FSWrite(fileRefNum,&bytesT
Then you need to read the length back:
bytesToRead = sizeof(SInt32)
FSRead(fileRefNum,&bytesTo
Then you can read the text:
bytesToRead = fieldOneLength;
FSRead(fileRefNum,&bytesTo
To put the text read from the file back into your TEHandle, use TESetText (as you are doing):
TESetText(*textBuffer1,fie
ASKER
Thank you boonstra. Now it works, but when it reads back the text, the text does not appear right (it appears &a!/´é'@%^*). Also, there is a lot of stuff inside each field.
Here is the code again, which I revised including arrays:
// .......................... .......... .......... .. doSaveAsFile
void doSaveAsFile(void)
{
StandardFileReply fileReply;
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldLength[100];
DocRecHandle docRecHdl;
TEHandle fieldHdl[100];
int i=0, j=0,m=0, n=0;
SInt32 bytesToWrite;
bytesToWrite = sizeof(SInt32); // boonstra suggestion
StandardPutFile("\pSave as:","\puntitled",&fileRep ly);
if(fileReply.sfGood)
{
windowPtr = FrontWindow();
SetWTitle(windowPtr,fileRe ply.sfFile .name);
if(!(fileReply.sfReplacing ))
FSpCreate(&fileReply.sfFil e,'????',' TEXT',file Reply.sfSc ript);
FSpOpenDF(&fileReply.sfFil e,fsCurPer m,&fileRef Num);
for(i=0; i<gMaxFields; i++)
{
fieldLength[i] = (*(*docRecHdl)->inputHdl[i ])->teLeng th;
fieldHdl[i] = (*docRecHdl)->inputHdl[i];
}
for(j=0; j<gMaxFields; j++)
{
FSWrite(fileRefNum,&bytesT oWrite,&fi eldLength[ j]); // boonstra suggestion
}
for(m=0; m<gMaxFields; m++)
{
FSWrite(fileRefNum,&fieldL ength[m],* fieldHdl[m ]);
}
FSClose(fileRefNum);
}
}
// .......................... .......... .......... .. doOpenCommand
void doOpenCommand(void)
{
StandardFileReply fileReply;
SFTypeList fileTypes;
fileTypes[0] = 'TEXT';
StandardGetFile(NULL,1,fil eTypes,&fi leReply);
if(fileReply.sfGood)
doOpenFile(fileReply.sfFil e);
}
// .......................... .......... .......... .. doOpenFile
void doOpenFile(FSSpec fileSpec)
{
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldLength[100]; //textLength
DocRecHandle docRecHdl;
TEHandle fieldHdl[100];
int i=0, j=0, m=0, n=0, p=0, r=0, s=0, t=0, v=0;
Handle textBuffer[100];
SInt32 bytesToRead;
bytesToRead = sizeof(SInt32); // boonstra suggestion
openWindow();
docRecHdl = (DocRecHandle) (GetWRefCon(gWindowPtr));
for(i=0; i<gMaxFields;i++)
{
fieldHdl[i] = (*docRecHdl)->inputHdl[i];
}
SetWTitle(gWindowPtr,fileS pec.name);
FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);
SetFPos(fileRefNum,fsFromS tart,0);
for(j=0; j<gMaxFields; j++)
{
GetEOF(fileRefNum,&fieldLe ngth[j]);
}
for(m=0; m<gMaxFields; m++)
{
if(fieldLength[m] > 32767 )
fieldLength[m] = 32767;
}
for(n=0; n<gMaxFields; n++)
{
textBuffer[n] = NewHandle((Size) fieldLength[n]);
}
for(p=0; p<gMaxFields; p++)
{
FSRead(fileRefNum,&bytesTo Read,&fiel dLength[p] ); // read the length back
}
for(r=0; r<gMaxFields; r++)
{
bytesToRead = fieldLength[r];
FSRead(fileRefNum,&bytesTo Read,*text Buffer[r]) ; //read the text
}
for(s=0; s<gMaxFields; s++)
{
MoveHHi(textBuffer[s]);
HLock(textBuffer[s]);
}
for( t=0; t<gMaxFields; t++)
{
TESetText(*textBuffer[t], fieldLength[t], fieldHdl[t]); // put the text read from the file back into your TEHandle
}
for(v=0; v<gMaxFields; v++)
{
HUnlock(textBuffer[v]);
DisposeHandle(textBuffer[v ]);
}
FSClose(fileRefNum);
(*fieldHdl[0])->selStart = 0;
(*fieldHdl[0])->selEnd = 0;
ShowWindow(gWindowPtr);
}
Here is the code again, which I revised including arrays:
// ..........................
void doSaveAsFile(void)
{
StandardFileReply fileReply;
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldLength[100];
DocRecHandle docRecHdl;
TEHandle fieldHdl[100];
int i=0, j=0,m=0, n=0;
SInt32 bytesToWrite;
bytesToWrite = sizeof(SInt32); // boonstra suggestion
StandardPutFile("\pSave as:","\puntitled",&fileRep
if(fileReply.sfGood)
{
windowPtr = FrontWindow();
SetWTitle(windowPtr,fileRe
if(!(fileReply.sfReplacing
FSpCreate(&fileReply.sfFil
FSpOpenDF(&fileReply.sfFil
for(i=0; i<gMaxFields; i++)
{
fieldLength[i] = (*(*docRecHdl)->inputHdl[i
fieldHdl[i] = (*docRecHdl)->inputHdl[i];
}
for(j=0; j<gMaxFields; j++)
{
FSWrite(fileRefNum,&bytesT
}
for(m=0; m<gMaxFields; m++)
{
FSWrite(fileRefNum,&fieldL
}
FSClose(fileRefNum);
}
}
// ..........................
void doOpenCommand(void)
{
StandardFileReply fileReply;
SFTypeList fileTypes;
fileTypes[0] = 'TEXT';
StandardGetFile(NULL,1,fil
if(fileReply.sfGood)
doOpenFile(fileReply.sfFil
}
// ..........................
void doOpenFile(FSSpec fileSpec)
{
WindowPtr windowPtr;
SInt16 fileRefNum;
SInt32 fieldLength[100]; //textLength
DocRecHandle docRecHdl;
TEHandle fieldHdl[100];
int i=0, j=0, m=0, n=0, p=0, r=0, s=0, t=0, v=0;
Handle textBuffer[100];
SInt32 bytesToRead;
bytesToRead = sizeof(SInt32); // boonstra suggestion
openWindow();
docRecHdl = (DocRecHandle) (GetWRefCon(gWindowPtr));
for(i=0; i<gMaxFields;i++)
{
fieldHdl[i] = (*docRecHdl)->inputHdl[i];
}
SetWTitle(gWindowPtr,fileS
FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);
SetFPos(fileRefNum,fsFromS
for(j=0; j<gMaxFields; j++)
{
GetEOF(fileRefNum,&fieldLe
}
for(m=0; m<gMaxFields; m++)
{
if(fieldLength[m] > 32767 )
fieldLength[m] = 32767;
}
for(n=0; n<gMaxFields; n++)
{
textBuffer[n] = NewHandle((Size) fieldLength[n]);
}
for(p=0; p<gMaxFields; p++)
{
FSRead(fileRefNum,&bytesTo
}
for(r=0; r<gMaxFields; r++)
{
bytesToRead = fieldLength[r];
FSRead(fileRefNum,&bytesTo
}
for(s=0; s<gMaxFields; s++)
{
MoveHHi(textBuffer[s]);
HLock(textBuffer[s]);
}
for( t=0; t<gMaxFields; t++)
{
TESetText(*textBuffer[t], fieldLength[t], fieldHdl[t]); // put the text read from the file back into your TEHandle
}
for(v=0; v<gMaxFields; v++)
{
HUnlock(textBuffer[v]);
DisposeHandle(textBuffer[v
}
FSClose(fileRefNum);
(*fieldHdl[0])->selStart = 0;
(*fieldHdl[0])->selEnd = 0;
ShowWindow(gWindowPtr);
}
You need to write out of the hText field of fieldHdl, i.e., replace
FSWrite(fileRefNum,&fieldL ength[m],( *fieldHdl[ m]); //bad
with
FSWrite(fileRefNum,&fieldL ength[m],* (**fieldHd l[m]).hTex t);
Also, you should set bytesToRead to sizeof(SInt32) inside of the fieldLength read loop, as it is overwritten with each FSRead. Same with the fieldLength write loop, although it will only matter if there is a problem with the write.
I'd also recommend an HGetState, HLock, FSWrite, HSetState around the text write code to prevent memory from moving during the FSWrite.
FSWrite(fileRefNum,&fieldL
with
FSWrite(fileRefNum,&fieldL
Also, you should set bytesToRead to sizeof(SInt32) inside of the fieldLength read loop, as it is overwritten with each FSRead. Same with the fieldLength write loop, although it will only matter if there is a problem with the write.
I'd also recommend an HGetState, HLock, FSWrite, HSetState around the text write code to prevent memory from moving during the FSWrite.
ASKER