4 Replies Latest reply on May 28, 2015 5:04 AM by Andreas Jansson

    Breaking change in F_ApiSimpleSave saving documents in FrameMaker12

    Andreas Jansson Level 2

      Hi,

       

      I was asked to repeat this question under "scripting", and hope someone can help us out.

       

      We have document files generated as MIF. We then call F_ApiSimpleSave to have FrameMaker produce fm files as described in http://www.adobe.com/content/dam/Adobe/en/devnet/framemaker/fdk/10/fdkprogrammerguide.pdf), p 253.

       

      In version 12 of FrameMaker the F_ApiSimpleSave call obviously results in "View only" files. I'm not familiar with that format, but in our case it's not good at all.

      The call to produce fm files from MIF has been unchanged for many years and versions of FrameMaker.

       

      Why does the F_ApiSimpleSave call to FrameMaker produce these read only ("locked" or "View only") files, and more important: what can be done about it?

       

      The original question can be found here:

      Error report saying: Couldn´t update this book, because it contains no openable nongenerated files

       

      Thanks,

      Andreas

        • 1. Re: Breaking change in F_ApiSimpleSave saving documents in FrameMaker12
          Russ Ward Level 4

          Andreas,

           

          I can't explain why your documents are becoming view-only with F_ApiSimpleSave(), but I can say that it is very simple to convert a view-only document back to editable status:

           

          F_ApiSetInt(FV_SessionId, docId, FP_DocIsViewOnly, False);

           

          By the way, F_ApiSimpleSave() seems attractive at first due to its simplicity, but I've found that the lack of precision makes it inadequate for most operations. While you have to deal with more parameters, F_ApiSave() is much better because you have very specific control over what happens.

           

          Russ

          • 2. Re: Breaking change in F_ApiSimpleSave saving documents in FrameMaker12
            Andreas Jansson Level 2

            Thank you Russ!

             

            I just discovered that the .fm files produced by F_ApiSimpleSave() when running FM12 are in fact MIF files, similar to the original MIF files generated by our application. It seems F_ApiSimpleSave() does not save the file as binary fm any longer. Perhaps that is causing the "View only" as well(?).

             

            F_ApiSimpleSave() did work fine for at least 13 years. I believe it's just called upon to save the mif-files as fm...

             

            Could it be a bug, that Adobe would want to fix? Otherwise we will have to look into F_ApiSave.

            • 3. Re: Breaking change in F_ApiSimpleSave saving documents in FrameMaker12
              Russ Ward Level 4

              Andreas,

               

              There were changes in recent releases that were related to file formats, such as the ability to put non-binary files in books. This effort has improved the handling of native file formats, but maybe it also affected F_ApiSimpleSave() too. I don't know. I would, however, strongly recommend F_ApiSave(), as it is much more reliable. Below is a function I use for saving files. It has some quirks related to my own personal needs, but hopefully you can make some sense of it. Warning - it is littered with references to other functions that you don't have. Things like ds() which is my shortcut to deallocate a string and sie() which is my shortcut to check for an empty string. So, it won't just work as-is for you, but maybe it can be of some use.

               

              Russ

               

              
              //////////////////////////////////////////////////////////////
              /////////////////////////////////////////////////////////////
              // Two things... to do a Save As, send a path. Also, normally
              // send -1 for the fileType unless you want to change it from the
              // extention of the target path. This function will figure it out
              // based on the extension if you do not send it.
              // Options:
              //FV_SaveFmtXml
              //FV_SaveFmtSgml
              //FV_SaveFmtInterchange
              //FV_SaveFmtText
              //FV_SaveFmtBinary
              
              // 4/7/2014  NEW  to specify a structure application,
              // append it to the path following two colons. Or,
              // if a docID is sent, send it for the path, preceeded
              // by two colons.
              
              // 5/20/2015 NEW, to save as RTF, send 100 for the file type.
              // YOU MUST SEND THE PATH TOO.
              
              F_ObjHandleT ws_SaveFile(F_ObjHandleT docId,
                                       StringT path,
                                       IntT fileType,
                                       IntT ignoreErrors,
                                       IntT doBackup,
                                       IntT notifyAPIClients)
              {
                F_PropValsT saveScript, *returnp = NULL;
                  
                UIntT sn;
              
                StringT tempPath,
                  structApp;
              
                F_StringsT tempStrings;
                
                if(ws_StrIndexOf(path, "::", 0, False) > -1)
                {
                  tempStrings = ws_GetArgumentsFromString_2(path, "::");
              
                  if(sie(tempStrings.val[0]))
                    tempPath = F_ApiGetString(FV_SessionId, docId, FP_Name);
                  else tempPath = cs(tempStrings.val[0]);
              
                  if(tempStrings.len > 1) structApp = cs(tempStrings.val[1]);
                  else structApp = cs("");
              
                  dss(&tempStrings);
                }
                else if(sie(path))
                {
                  tempPath = F_ApiGetString(FV_SessionId, docId, FP_Name);
                  structApp = cs("");
                }
                else
                {
                  tempPath = F_ApiCopyString(path);
                  structApp = cs("");
                }
              
              
                //let's figure out the fileType if we don't have one
                if(fileType < 0)
                {
                  if(ws_StrIsSuffix(tempPath, ".xml", False))
                    fileType = FV_SaveFmtXml;
              
                  else if(ws_StrIsSuffix(tempPath, ".sgml", False))
                    fileType = FV_SaveFmtSgml;
              
                  else if(ws_StrIsSuffix(tempPath, ".mif", False))
                    fileType = FV_SaveFmtInterchange;
              
                  else if(ws_StrIsSuffix(tempPath, ".txt", False))
                    fileType = FV_SaveFmtText;
              
                  else if(ws_StrIsSuffix(tempPath, ".pdf", False))
                    fileType = FV_SaveFmtPdf;
              
                  else
                    fileType = FV_SaveFmtBinary;
                }
              
                  
                saveScript = F_ApiGetSaveDefaultParams();
              
                sn = F_ApiGetPropIndex(&saveScript, FS_AlertUserAboutFailure);
                if(ignoreErrors)
                    saveScript.val[sn].propVal.u.ival = False;
                else
                    saveScript.val[sn].propVal.u.ival = True;
              
                  sn = F_ApiGetPropIndex(&saveScript, FS_AutoBackupOnSave);
                if(doBackup)
                    saveScript.val[sn].propVal.u.ival = FV_SaveYesAutoBackup;
                else
                    saveScript.val[sn].propVal.u.ival = FV_SaveNoAutoBackup;
              
                sn = F_ApiGetPropIndex(&saveScript, FS_DontNotifyAPIClients);
                if(notifyAPIClients)
                    saveScript.val[sn].propVal.u.ival = False;
                else
                    saveScript.val[sn].propVal.u.ival = True;
              
                //File type
                sn = F_ApiGetPropIndex(&saveScript, FS_FileType);
              
                //For RTF, a hack
                if(fileType == 100)
                {
                    saveScript.val[sn].propVal.u.ival = FV_SaveFmtFilter;
              
                    sn = F_ApiGetPropIndex(&saveScript, FS_SaveFileTypeHint);
                  ds(&saveScript.val[sn].propVal.u.sval);
                  saveScript.val[sn].propVal.u.sval = cs("0001ADBIRTF         Microsoft RTF1.6");
                }
              
              
                else
                {
                    saveScript.val[sn].propVal.u.ival = fileType;
                }
              
                  sn = F_ApiGetPropIndex(&saveScript, FS_RetainNameStripe);
                saveScript.val[sn].propVal.u.ival = False;
                  
                //if we didn't have a path, it's just a save, but only
                //for binaries. All other file formats are always a Save As.
                if(sie(path) && fileType == FV_SaveFmtBinary)
                {
                    sn = F_ApiGetPropIndex(&saveScript, FS_SaveMode);
                  saveScript.val[sn].propVal.u.ival = FV_ModeSave;
              
                  sn = F_ApiGetPropIndex(&saveScript, FS_SaveAsModeName);
                  saveScript.val[sn].propVal.u.ival = FV_SaveAsUseFileName;
              
                }
                else
                {
                    sn = F_ApiGetPropIndex(&saveScript, FS_SaveMode);
                  saveScript.val[sn].propVal.u.ival = FV_ModeSaveAs;
              
                  sn = F_ApiGetPropIndex(&saveScript, FS_SaveAsModeName);
                  saveScript.val[sn].propVal.u.ival = FV_SaveAsNameProvided;
                }
              
                if(fileType == FV_SaveFmtXml ||
                   fileType == FV_SaveFmtSgml)
                {
                    sn = F_ApiGetPropIndex(&saveScript, FS_StructuredSaveApplication);
                  ds(&saveScript.val[sn].propVal.u.sval);
                  saveScript.val[sn].propVal.u.sval = cs(structApp);
                }
              
                
              
                //save the document
                docId = F_ApiSave(docId, tempPath, &saveScript, &returnp);
              
                //we are done with these structures, so deallocate
                F_ApiDeallocatePropVals(&saveScript);
                F_ApiDeallocatePropVals(returnp);
              
                //if something went wrong, ensure the return value is zero
                if(!docId) docId = 0;
              
                F_ApiDeallocateString(&tempPath);
                F_ApiDeallocateString(&structApp);
              
                //F_ApiPrintFAErrno();
                  
                return docId;
              
              }
              
              
              • 4. Re: Breaking change in F_ApiSimpleSave saving documents in FrameMaker12
                Andreas Jansson Level 2

                Great! I managed to recompile the old c++ dll with a simplified version of your example (added below).

                 

                To make it compatible with the "simple save" function that I already had, I changed the name and parameters (names and types) to the same as the old function had.

                 

                The only thing left is that fdk.lib now references icuuc32.dll, icuin32.dll and netlib.dll, which exist in the FrameMaker folder (in program files / Program files(x86) or similar). I guess I will have to write some code to try and add the framemaker folder to the PATH environment variable, for the clients that are going to run this.

                 

                int __stdcall FMSaveDoc(int nDocID, LPCSTR lpszSaveAsName, BOOL bInteractive)
                {
                
                    F_PropValsT saveScript, *returnp = NULL;
                
                    UIntT sn;
                
                    saveScript = F_ApiGetSaveDefaultParams();
                
                    sn = F_ApiGetPropIndex(&saveScript, FS_AlertUserAboutFailure);
                    if (bInteractive)
                        saveScript.val[sn].propVal.u.ival = False;
                    else
                        saveScript.val[sn].propVal.u.ival = True;
                
                    sn = F_ApiGetPropIndex(&saveScript, FS_AutoBackupOnSave);
                    saveScript.val[sn].propVal.u.ival = FV_SaveNoAutoBackup;
                
                    // File type  - Binary format of current InDesign version.
                    sn = F_ApiGetPropIndex(&saveScript, FS_FileType);
                    saveScript.val[sn].propVal.u.ival = FV_SaveFmtBinary;
                    
                    sn = F_ApiGetPropIndex(&saveScript, FS_RetainNameStripe);
                    saveScript.val[sn].propVal.u.ival = False;
                    
                    sn = F_ApiGetPropIndex(&saveScript, FS_SaveMode);
                    saveScript.val[sn].propVal.u.ival = FV_ModeSaveAs;
                
                    sn = F_ApiGetPropIndex(&saveScript, FS_SaveAsModeName);
                    saveScript.val[sn].propVal.u.ival = FV_SaveAsNameProvided;
                    
                    // Save the document  
                    nDocID = F_ApiSave(nDocID, (StringT)lpszSaveAsName, &saveScript, &returnp);
                
                    // We are done with these structures, so deallocate  
                    F_ApiDeallocatePropVals(&saveScript);
                    F_ApiDeallocatePropVals(returnp);
                
                    // If something went wrong, ensure the return value is zero  
                    if (!nDocID) nDocID = 0;
                
                    return nDocID;
                
                }