Link to home
Start Free TrialLog in
Avatar of supersax
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.
ASKER CERTIFIED SOLUTION
Avatar of boonstra
boonstra

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of supersax
supersax

ASKER

Ok boonstra, what you say makes sense. But, since I do not have a lot of experience, I need to see a sample of code that does that. Eventually if you can show me the code at least for two field inputs. (Anyway, I'm able to extract the text properly with StringToExtended and ExtendedToString).
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,sizeof(char),lng,outFile);
      HSetState((**teH).hText,state);
}

static void ReadTEH(TEHandle teH,long lng, FILE *inFile)
{
      unsigned char state;
      state = HGetState((**teH).hText);
      HLock((**teH).hText);
      fread(*(**teH).hText,sizeof(char),lng,inFile);
      HSetState((**teH).hText,state);
}

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(text1),te1);
      TEInsert(text2,strlen(text2),te2);
      
/* write file */
      outFile = fopen("test.out","w");
      if (0==outFile) DebugStr("\p unable to open output file");
      
      size1 = GetHandleSize((**te1).hText);
      size2 = GetHandleSize((**te2).hText);
      
      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);
      
      
}


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",&fileReply);
      if(fileReply.sfGood)
      {
            windowPtr = FrontWindow();
            SetWTitle(windowPtr,fileReply.sfFile.name);

            if(!(fileReply.sfReplacing))
                  FSpCreate(&fileReply.sfFile,'????','TEXT',fileReply.sfScript);

            FSpOpenDF(&fileReply.sfFile,fsCurPerm,&fileRefNum);

            fieldOneLength = (*(*docRecHdl)->inputFieldOneHdl)->teLength;
            fieldTwoLength = (*(*docRecHdl)->inputFieldTwoHdl)->teLength;
            
            fieldOneHdl = (*docRecHdl)->inputFieldOneHdl;
            fieldTwoHdl = (*docRecHdl)->inputFieldTwoHdl;            
            
            FSWrite(fileRefNum,&fieldOneLength,*fieldOneHdl);
            FSWrite(fileRefNum,&fieldTwoLength,*fieldTwoHdl);
            
            FSClose(fileRefNum);
      }
}

???????????? doOpenCommand

void  doOpenCommand(void)
{
      StandardFileReply      fileReply;
      SFTypeList                        fileTypes;      

      fileTypes[0] = 'TEXT';

      StandardGetFile(NULL,1,fileTypes,&fileReply);
      if(fileReply.sfGood)
            doOpenFile(fileReply.sfFile);
}

// ?????????? 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)->inputFieldOneHdl;
      fieldTwoHdl = (*docRecHdl)->inputFieldTwoHdl;

      SetWTitle(windowPtr,fileSpec.name);
      
      FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);

      SetFPos(fileRefNum,fsFromStart,0);
      GetEOF(fileRefNum,&fieldOneLength);
      GetEOF(fileRefNum,&fieldTwoLength);

      if(fieldOneLength > 32767 )
            fieldOneLength = 32767;

      textBuffer1 = NewHandle((Size) fieldOneLength);
      textBuffer2 = NewHandle((Size) fieldTwoLength);

      FSRead(fileRefNum,&fieldOneLength,*textBuffer1);
      FSRead(fileRefNum,&fieldTwoLength,*textBuffer2);

      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);
}
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,&bytesToWrite,&fieldOneLength);

Then you need to read the length back:
  bytesToRead = sizeof(SInt32)
  FSRead(fileRefNum,&bytesToRead,&fieldOneLength);

Then you can read the text:
  bytesToRead = fieldOneLength;
  FSRead(fileRefNum,&bytesToRead,*textBuffer1);

To put the text read from the file back into your TEHandle, use TESetText (as you are doing):

TESetText(*textBuffer1,fieldOneLength,fieldOneHdl);
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",&fileReply);
      if(fileReply.sfGood)
      {
            windowPtr = FrontWindow();
            SetWTitle(windowPtr,fileReply.sfFile.name);

            if(!(fileReply.sfReplacing))
            FSpCreate(&fileReply.sfFile,'????','TEXT',fileReply.sfScript);

            FSpOpenDF(&fileReply.sfFile,fsCurPerm,&fileRefNum);

            for(i=0; i<gMaxFields; i++)
            {
                  fieldLength[i] =   (*(*docRecHdl)->inputHdl[i])->teLength;
                  fieldHdl[i] =   (*docRecHdl)->inputHdl[i];
            }
            
            for(j=0; j<gMaxFields; j++)
            {
                  FSWrite(fileRefNum,&bytesToWrite,&fieldLength[j]); // boonstra suggestion
            }

            for(m=0; m<gMaxFields; m++)
            {
                  FSWrite(fileRefNum,&fieldLength[m],*fieldHdl[m]);
            }

            FSClose(fileRefNum);
      }
}

// ................................................ doOpenCommand

void      doOpenCommand(void)
{
      StandardFileReply fileReply;
      SFTypeList fileTypes;

      fileTypes[0] = 'TEXT';

      StandardGetFile(NULL,1,fileTypes,&fileReply);
      if(fileReply.sfGood)
      doOpenFile(fileReply.sfFile);
}

// ................................................ 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,fileSpec.name);

      FSpOpenDF(&fileSpec, fsCurPerm, &fileRefNum);

      SetFPos(fileRefNum,fsFromStart,0);
      
      for(j=0; j<gMaxFields; j++)
      {
            GetEOF(fileRefNum,&fieldLength[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,&bytesToRead,&fieldLength[p]); // read the length back
      }
      
      for(r=0; r<gMaxFields; r++)
      {
            bytesToRead = fieldLength[r];
            FSRead(fileRefNum,&bytesToRead,*textBuffer[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);
}

You need to write out of the hText field of fieldHdl, i.e., replace

FSWrite(fileRefNum,&fieldLength[m],(*fieldHdl[m]); //bad

with

FSWrite(fileRefNum,&fieldLength[m],*(**fieldHdl[m]).hText);

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.