Solved

Saving text from 4 fields to a file

Posted on 1999-01-29
7
244 Views
Last Modified: 2013-12-26
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.
0
Comment
Question by:supersax
  • 4
  • 3
7 Comments
 
LVL 3

Accepted Solution

by:
boonstra earned 50 total points
ID: 1291782
You haven't said how you input the data, but since you are able to write it to a file, you must be able to extract it properly.  It seems that your problem is that you cannot separate the individual field values once you have written them.

I'd suggest writing four 4-byte values at the start of the file, the GetHandleSize() values for each of your four TEHandles.  Then write GetHandleSize(teH) bytes of text for each of the four teH TEHandles.

When reading the file, first read len1,len2,len3, and len4, the four 4-byte length values.  Then read len1 characters into the first field, then len2 into the second field, etc.
0
 

Author Comment

by:supersax
ID: 1291783
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).
0
 
LVL 3

Expert Comment

by:boonstra
ID: 1291784
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);
      
      
}


0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:supersax
ID: 1291785
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);
}
0
 
LVL 3

Expert Comment

by:boonstra
ID: 1291786
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);
0
 

Author Comment

by:supersax
ID: 1291787
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);
}

0
 
LVL 3

Expert Comment

by:boonstra
ID: 1291788
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.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

790 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question