Breaking change in F_ApiSimpleSave saving documents in FrameMaker12

Enthusiast ,
May 25, 2015 May 25, 2015

Copy link to clipboard

Copied

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

TOPICS
Scripting

Views

497

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct Answer

Mentor , May 26, 2015 May 26, 2015
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 li...

Likes

translate

Translate

Translate
Mentor ,
May 26, 2015 May 26, 2015

Copy link to clipboard

Copied

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

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
May 26, 2015 May 26, 2015

Copy link to clipboard

Copied

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.

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
May 26, 2015 May 26, 2015

Copy link to clipboard

Copied

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;

}

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
May 28, 2015 May 28, 2015

Copy link to clipboard

Copied

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;

}

Likes

translate

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines