?
Solved

Saving text from 4 fields to a file

Posted on 1999-01-29
7
Medium Priority
?
262 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 3

Accepted Solution

by:
boonstra earned 150 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

765 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