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
1 Correct answer
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
...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
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.
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;
}
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;
}

