Adobe FDK Programmer’s Guide Frame Maker 12.0 Programmer’s Reference Fm 12 Rg En

User Manual: adobe FrameMaker - 12.0 - FDK Programmer’s Reference Free User Guide for Adobe FrameMaker Software, Manual

Open the PDF directly: View PDF PDF.
Page Count: 560

DownloadAdobe FDK Programmer’s Guide Frame Maker - 12.0 Programmer’s Reference Fm 12 Rg En
Open PDF In BrowserView PDF
FDK Programmer’s Guide
V E R S I O N

1 2

ADOBE SYSTEMS INCORPORATED

Frame Developer’s Kit, January 2014

Corporate Headquarters
345 Park Avenue
San Jose, CA 95110-2704
(408) 536-6000

I M P O R TA N T N O T I C E

© Copyright 1986 - 2014 Adobe Systems Incorporated and its licensors. All rights reserved.
Adobe, the Adobe logo & FrameMaker are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
Certain trademarks are owned by The Proximity Division of Franklin Electronic Publishers, Inc., and are used by permission. Merriam-Webster is a trademark
of Merriam-Webster, Inc.
Portion include technology under Inso Corporation.
Portions include technology under copyright Right Hemisphere, Inc.
Portions utilize Microsoft Windows Media Technologies. Copyright (c) 2006 Microsoft Corporation. All Rights Reserved.
Notices, terms and conditions pertaining to third party software are located at http://www.adobe.com/go/thirdparty and incorporated by reference herein.

Contents

.....

..................................

PA RT I : G e t t i n g Sta r t e d
U s i n g F r a m e D e v e l o p e r To o l s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
The Frame Developer’s Kit .......................................................................................... 11
Choosing the right Frame tools ..................................................................................... 13
FDK documentation ...................................................................................................... 14
Naming conventions ..................................................................................................... 14
Style conventions .......................................................................................................... 15
G e t t i n g S t a r t e d w i t h F D K 1 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Downloading and installing the FDK ........................................................................... 18
System requirements ..................................................................................................... 18
Reviewing the sample programs in the samples/hello folder ....................................... 19
Getting familiar with how the FDK works on Windows .............................................. 20
Writing FDK clients for Windows ................................................................................ 21
Compiling, Registering, and Running FDK Clients ..................................................... 28
Writing an Asynchronous FDK Client ......................................................................... 39
Example: adding menus and commands ....................................................................... 55
Next Steps ..................................................................................................................... 57

PA RT I I : F ra m e P ro d u c t A rc h i t e c t u re
1

Frame Session Architecture ....................................................................................... 61
Identifying objects ........................................................................................................ 61
Representing object characteristics with properties ...................................................... 63
FrameMaker product sessions ...................................................................................... 67

2

Frame Document Architecture .................................................................................. 73
Documents .................................................................................................................... 73
Global document information ....................................................................................... 79
Pages ............................................................................................................................. 85
Graphic objects ............................................................................................................. 90
Flows ............................................................................................................................. 95
Paragraph Catalog formats .......................................................................................... 100
Paragraphs ................................................................................................................... 101
Character Catalog formats .......................................................................................... 106
Condition Formats ...................................................................................................... 110

FDK Programmer’s Guide

3

Contents

Text ............................................................................................................................. 112
Markers ....................................................................................................................... 122
Cross-reference formats .............................................................................................. 125
Cross-references .......................................................................................................... 127
Variable formats .......................................................................................................... 129
Variables ...................................................................................................................... 131
Footnotes ..................................................................................................................... 132
Ruling Formats ........................................................................................................... 134
Table Catalog formats ................................................................................................. 136
Tables .......................................................................................................................... 138
Colors .......................................................................................................................... 147
Structural element definitions ..................................................................................... 150
Format rules and format rule clauses .......................................................................... 153
Format change lists ..................................................................................................... 155
Structural elements ..................................................................................................... 157
3

Frame Book Architecture ......................................................................................... 159
What the user sees ....................................................................................................... 159
How the API represents books .................................................................................... 160
Creating new books and components ......................................................................... 164
Updating a book .......................................................................................................... 165
Using the book error log ............................................................................................. 170

PA RT I I I : F r a m e A p p l i c a t i o n P ro g r a m I n t e r f a c e

4

FDK Programmer’s Guide

1

Introduction to the Frame API ................................................................................ 175
How the API works ..................................................................................................... 175
Special types of clients ............................................................................................... 177
Running clients with different FrameMaker product interfaces ................................. 179
Creating and running a client ...................................................................................... 179
A simple example ....................................................................................................... 181
Using old clients with FDK 12 ................................................................................... 185

2

API Client Initialization ........................................................................................... 187
Responding to the FrameMaker product’s initialization call ...................................... 187
Initialization types ....................................................................................................... 188
Disabling the API ........................................................................................................ 190
FrameMaker Product Activation by Asynchronous Clients ....................................... 190

3

Creating Your Client’s
User Interface 193
Using API dialog boxes to prompt the user for input ................................................. 193
Using commands, menu items, and menus in your client .......................................... 203
Replacing FrameMaker product menus and commands ............................................. 211
Allowing users to configure your client’s interface .................................................... 211

...

Contents

Using hypertext commands in your client’s user interface ......................................... 213
Responding to user-initiated events or FrameMaker product operations ................... 217
Implementing quick keys ............................................................................................ 228
Freeing system resources by bailing out ..................................................................... 230
4

Executing Commands with API Functions ............................................................ 233
Handling errors ........................................................................................................... 233
Handling messages and warnings ............................................................................... 233
Opening documents and books ................................................................................... 235
Creating documents .................................................................................................... 244
Printing documents and books .................................................................................... 249
Saving documents and books ...................................................................................... 251
Closing documents and books .................................................................................... 258
Quitting a Frame session ............................................................................................. 260
Comparing documents and books ............................................................................... 260
Updating and generating documents and books ......................................................... 263
Simulating user input .................................................................................................. 270
Straddling table cells ................................................................................................... 271
Executing FrameMaker commands ............................................................................ 272

5

Getting and Setting Properties ................................................................................ 277
What you can do with object properties ..................................................................... 277
Getting the IDs of the objects you want to change ..................................................... 278
Manipulating properties .............................................................................................. 288
Getting and setting session properties ........................................................................ 295
Getting and setting document properties .................................................................... 298
Getting and setting graphic object properties ............................................................. 301
Getting and setting paragraph properties .................................................................... 304
Getting and setting book properties ............................................................................ 308
Getting and setting FrameMaker properties ............................................................... 309

6

Manipulating Text ..................................................................................................... 317
Getting text ................................................................................................................. 317
Getting and setting the insertion point or text selection ............................................. 321
Adding and deleting text ............................................................................................. 331
Getting and setting text formatting ............................................................................. 334
Executing Clipboard functions ................................................................................... 339

7

Manipulating Asian Text .......................................................................................... 343
Creating a rubi group .................................................................................................. 343
Text encodings ............................................................................................................ 344
Using encoding data .................................................................................................... 346
Inspecting and manipulating encoded text .................................................................. 351
Parsing an encoded string ........................................................................................... 353
Getting the encoding for a text item ........................................................................... 355
Special issues with double byte encodings ................................................................. 355

FDK Programmer’s Guide

5

Contents

6

8

Creating and Deleting API Objects ......................................................................... 357
Creating objects .......................................................................................................... 357
Deleting objects .......................................................................................................... 377
Implicit property changes ........................................................................................... 379

9

Manipulating Commands and Menus with the API .............................................. 381
How the API represents commands and menus .......................................................... 381
Getting the IDs of commands and menus ................................................................... 385
Determining a session’s menu configuration .............................................................. 387
Arranging menus and menu items .............................................................................. 388
Getting and setting menu item labels .......................................................................... 395
Manipulating expandomatic menu items .................................................................... 397
Using check marks ...................................................................................................... 398
Using context-sensitive commands and menu items .................................................. 398

10

Creating Custom Dialog Boxes for Your Client ..................................................... 403
Overview ..................................................................................................................... 403
How to create a dialog box ......................................................................................... 408
Creating a DRE file ..................................................................................................... 408
Designing the layout of the dialog box ....................................................................... 411
Setting the properties of the dialog box ...................................................................... 415
Setting the properties of a dialog item ........................................................................ 419
Saving a DRE file ....................................................................................................... 427
Modeless Dialog Boxes .............................................................................................. 428
Testing a dialog box .................................................................................................... 429
A simple example ....................................................................................................... 431
General tips for dialog editing .................................................................................... 435
Summary of keyboard shortcuts ................................................................................. 435

11

Handling Custom Dialog Box Events ...................................................................... 437
How the API represents dialog boxes ......................................................................... 437
Overview of using a custom dialog box in your client ............................................... 440
Opening dialog resources ............................................................................................ 444
Initializing items in a dialog box ................................................................................ 445
Displaying a dialog box .............................................................................................. 446
Updating items in a dialog box ................................................................................... 447
Handling user actions in dialog boxes ........................................................................ 448
Closing a dialog box ................................................................................................... 457

12

Using Imported Files and Insets .............................................................................. 459
Types of imported files and insets .............................................................................. 459
Importing text and graphics ........................................................................................ 460
Updating text insets .................................................................................................... 467
Client text insets .......................................................................................................... 467
Writing filter clients .................................................................................................... 472
Specifying format IDs and filetype hint strings .......................................................... 476

FDK Programmer’s Guide

...

Contents

Associating a file format with signature bytes ............................................................ 488
13

Working with Unicode .............................................................................................. 501
Introduction to Unicode Support ................................................................................ 501
Unicode Mode ............................................................................................................. 501
Compatibility mode .................................................................................................... 511
International Components for Unicode (ICU) ............................................................ 519
Mixed Mode operations .............................................................................................. 521
Handling for special characters ................................................................................... 522

PA RT I V: F r a m e D e v e l o pment Envi ro nmen t (F DE)
14

Introduction to FDE ................................................................................................. 527
How the FDE works ................................................................................................... 527
How to make your client portable ............................................................................... 529
A simple FDE filter ..................................................................................................... 534

15

Making I/O and Memory Calls Portable ................................................................ 539
Initializing the FDE .................................................................................................... 539
Using platform-independent representations of pathnames ........................................ 539
Making I/O portable with channels ............................................................................ 543
Assertion-handler functions ........................................................................................ 543
Making memory allocation portable ........................................................................... 544
Error and progress reporting ....................................................................................... 545

16

FDE Utility Libraries ................................................................................................ 547
String library ............................................................................................................... 547
The string list library ................................................................................................... 548
Character library ......................................................................................................... 548
The I/O library ............................................................................................................ 549
The hash library .......................................................................................................... 549
Metric library .............................................................................................................. 551
MIF data structures and macros .................................................................................. 551
The MIF library .......................................................................................................... 553
Simple MIF library ..................................................................................................... 554

Glossary

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555

FDK Programmer’s Guide

7

Contents

8

FDK Programmer’s Guide

PART I

..........................................

Getting Started

U s i n g F r a m e D e v e l o p e r To o l s

.....

..................................

The Frame Developer’s Kit
The Frame Developer’s Kit™ (FDK) provides tools for developers to enhance the
functionality of FrameMaker.
This chapter provides an overview of the FDK and other aspects of FrameMaker that are
useful for developers. It also discusses the FDK documentation.
The principal parts of the FDK are:


Frame Application Program Interface™ (API)



Frame Development Environment™ (FDE)



Frame Structure Import/Export Application Program Interface (Structure
Import/Export API)

The following sections describe these parts and discuss how you can use them.

Frame API
The Frame API allows you to write C language programs, called FDK clients, that can
take control of a FrameMaker product session and communicate interactively with the
user. With the API, a client can do nearly anything an interactive user can do and more.
The API gives a client direct access to the text and graphic objects in documents. The
API includes a set of header files, libraries, and makefiles for each supported platform.
Here are some examples of the types of clients you can create with the API:


Grammar checkers



Bibliography utilities

FDK Programmer’s Guide

11

U s i n g F r a m e D e v e l o p e r To o l s

The Frame Developer’s Kit



Voice control utilities



Document reporting utilities



Version control systems for documents



Table utilities, such as sorting and totaling



Database publishing packages



Interfaces to document management systems



Filters to exchange files between other desktop publishing applications and
FrameMaker products

FDE
The Frame Development Environment (FDE) provides platform-independent
alternatives to platform-specific I/O, string, and memory allocation schemes. It also
provides a variety of utility functions, such as Maker Interchange Format (MIF) writing
functions.

Structure Import/Export API
The Structure Import/Export API allows you to write clients that control the import of
markup documents into FrameMaker, and control the export of FrameMaker documents
to markup.

Other FrameMaker product features for developers
FrameMaker provides other advanced features that are useful for developers. You do
not need the FDK to use these features.

MIF
Maker Interchange Format (MIF) is an easily parsed ASCII format that describes a
document’s text, graphics, formatting, and layout. FrameMaker can save a document or
a book to a MIF file, and convert a MIF file back to a document or book, without losing
any information.
You can write applications or scripts that convert a MIF file to the format of another
desktop publishing package, or convert other formats to MIF.
Here are some examples of things you can use MIF for:

12



Sharing files with earlier releases of FrameMaker products



Converting database files into Frame documents

FDK Programmer’s Guide

Choosing the right Frame tools



...

U s i n g F r a m e D e v e l o p e r To o l s

Filtering word processor documents into Frame documents

You can find documentation for MIF in the online manuals folder for your FrameMaker
installation.

Choosing the right Frame tools
There are often several tools or combinations of tools that you can use to solve a given
problem. In particular, you can use the API to perform many of the tasks that MIF and
fmbatch perform. The tool or combination of tools you should use depends on your
needs. Generally, MIF and fmbatch are more useful for one-time solutions to small
problems, whereas the API is more useful for full-scale applications or applications
where interaction with the user is required.
The following table summarizes the advantages and limitations of each Frame tool.
Frame tool
or feature

Advantages

Limitations

Frame API

Fast, interactive, and portable; easy to
provide a user interface for your
applications

Must be compiled

MIF

Can be used by text-processing
utilities. It can also be used to provide
“backwards” compatibility allowing
files to be opened in earlier releases of
the product. Third-party MIF creators
do not need to write complete MIF.
FrameMaker will always write out
complete MIF.

Files must be saved as MIF; not
interactive

FDK Programmer’s Guide

13

U s i n g F r a m e D e v e l o p e r To o l s

FDK documentation

FDK documentation
FDK documentation assumes that you have a thorough knowledge of FrameMaker .
For background information on FrameMaker, see your user documentation.
FDK documentation includes the following manuals, which are available in the doc
folder of your FDK installation.

FDK Programmer’s Reference
The FDK Programmer’s Reference provides FDK reference information, such as error
codes and data structure, function, and property descriptions.

FDK Programmer’s Guide
The FDK Programmer’s Guide is the guide you are reading now. It describes how to use
the FDK to create clients for FrameMaker. To get the most from this guide, you should
be familiar with the C programming language and event-driven programming.
The FDK Programmer’s Guide is divided into four parts:


Part I, "Getting Started," provides step-by-step guidance for getting familiar with the
FDK.



Part II, “Frame Product Architecture,” provides a conceptual overview of how the
API represents sessions, books, and documents.



Part III, "Frame Application Program Interface (API),” provides instructions for
creating API clients.



Part IV, "Frame Development Environment," provides instructions for making filters
and API clients platform-independent.

Naming conventions
To help you identify the structures, constants, and functions defined by the FDK, this
manual and the FDK adhere to the following naming conventions:

14

Type

Naming convention

Example

API error codes

Begin with FE_

FE_NotPgf

API functions

Begin with F_Api

F_ApiGetInt()

FDK Programmer’s Guide

Style conventions

...

U s i n g F r a m e D e v e l o p e r To o l s

Type

Naming convention

Example

API scriptable function
property names

Begin with FS_

FS_NewDoc

FDE functions

Begin with F_

F_StrNew()

Flags used by API functions

Begin with FF_ and all
letters are uppercase

FF_UFF_VAR

Initialization constants

Begin with FA_Init

FA_Init_First

Notification constants

Begin with FA_Note

FA_Note_PreFileType

Object property names

Begin with FP_

FP_Fill

Object types

Begin with FO_

FO_Doc

Property value constants

Begin with FV_

FV_Doc_Type_MIF

Typedefs

End with T

MetricT

This manual uses the term API graphic object to refer to objects (such as FO_Polygon
and FO_TextFrame objects) that the API uses to represent the graphic objects (such
as polygons and text frames) that appear on a page.

Style conventions
FDK manuals distinguish between you, the developer, and the user, the person for
whom you write clients.
FDK manuals may use the term FrameMaker product to refer to the FrameMaker
software, as opposed to the software you write to work with the FrameMaker product.

Structured program interface
FrameMaker 7.0 and later ships with two program interfaces—Structured FrameMaker
and FrameMaker. The structured program interface presents menus, icons, and
commands for working with structured documents. The FDK includes some functions
that only work on structured documents. For example, setting an element range makes
no sense in a document that doesn’t contain any structure elements. Further, you can
specify that an FDK client requires the Structured FrameMaker program interface. For
example, assume you specify Structured FrameMaker when you register your client. If
a user has your client installed, but is running the FrameMaker program interface (not
structured), then his installation of FrameMaker will not initialize your client when it
starts up.

FDK Programmer’s Guide

15

U s i n g F r a m e D e v e l o p e r To o l s

Style conventions

The FDK Programmer’s Reference indicates those FDK functions that apply only to
structured FrameMaker documents, as follows:

Structured F_ApiGetAttributeDefs()

In this example the word Structured appears to the left of the function name, indicating
that this function applies only to the content of a structured document. If you register a
client to work with the FrameMaker program interface, you should be sure that your
client doesn’t use any functions identified as Structured, otherwise your client may
exhibit unpredictable behavior.

Typographic conventions
This manual uses different fonts to represent different types of information.


What you type is shown in
text like this.



Function names, property names, structure names, returned values, constants, filter
names, program names, pathnames, and filenames are also shown in
text like this.



Placeholders (such as those representing names of files and directories) are shown in
text like this.

For example, this represents the name of your working directory:
\Mydir


Omitted code in source code examples is indicated with ellipses.
For example, the ellipsis in the following code indicates that some of the code
necessary to create a complete program is omitted:
. . .
F_ApiAlert((StringT)"Hello world.", FF_ALERT_CONTINUE_NOTE);
. . .

16

FDK Programmer’s Guide

G e t t i n g St a r t e d w i t h F D K 1 2

.....

..................................

This Getting Started section is intended to help you get familiar with the basics of FDK
12. It includes information on creating, compiling, running, and debugging FDK clients.
Sample code snippets are provided as pointers that you can build upon and create your
own FDK clients.
In this section:


"Downloading and installing the FDK"



"System requirements"



"Reviewing the sample programs in the samples/hello folder"



"Getting familiar with how the FDK works on Windows"



"Writing FDK clients for Windows"



"Compiling, Registering, and Running FDK Clients"



"Writing an Asynchronous FDK Client"



"Example: adding menus and commands"



"Next Steps"

FDK Programmer’s Guide

17

5

G e t t i n g St a r t e d w i t h F D K 1 2

Downloading and installing the FDK

Downloading and installing the FDK
Download the FrameMaker FDK from the FrameMaker Developer Center
http://www.adobe.com/devnet/framemaker.html

System requirements
Ensure that your system meets the following requirements:


Intel Pentium IV



Microsoft Windows XP, or Windows Vista or Windows 7



1GB of RAM



53MB of available hard-disk space

In addition, you should have Microsoft Visual Studio 2010 installed on the system.

18

FDK Programmer’s Guide

Reviewing the sample programs in the samples/hello folder

...

G e t t i n g St a r t e d w i t h F D K 1 2

Reviewing the sample programs in the samples/hello folder
The samples folder contains several programs that will help you get started. As an
example, here is a code extract from the samples/hello/hello.c file:
/*
* Program Name:
*

hello

*
* General Description:
*

Greets the user at product startup time.

*
* Invocation:
*

Once the client is installed, launch FrameMaker.

*
* Install Info (Windows):
*
Add the following entry (all on one line) to the
[APIClients]
*

section of your maker.ini file:

*
*
*

hello=Standard, Greets user at startup,
fdk_install_dir\samples\hello\debug\hello.dll, all

*
*

Replace fdk_install_dir with the path of the directory

*

in which you installed your copy of the FDK files.

*

Restart maker.

*
* Exceptions:
*

None.

*
****************************************************************
*******/

#include "fapi.h" /* required for all FDK client programs */
#include "fencode.h"

/* Call back invoked at product startup time */

FDK Programmer’s Guide

19

5

G e t t i n g St a r t e d w i t h F D K 1 2

Getting familiar with how the FDK works on Windows

VoidT F_ApiInitialize(init)
IntT init;
{
/* Making it unicode enabled. */
F_FdeInit();
F_ApiEnableUnicode(True);
F_FdeInitFontEncs("UTF-8");

Getting familiar with how the FDK works on Windows
FDK clients on Windows are not implemented as true Windows clients. They are
dynamic link libraries (DLLs) that provide entry points or callback functions, which
FrameMaker can invoke.
There are several types of FDK clients:


A standard FDK client is an FDK client that initializes when FrameMaker starts and
thenwaits to respond to specific user actions, such as menu choices.



A take-control client is an FDK client that responds to a special initialization and
takes complete control of a FrameMaker session. Many of the effectsyou can get
with this type of client can also be realized by an asynchronous client.



A filter is an FDK client that converts FrameMaker files to or from other file formats.
FrameMaker calls a filter when the user attempts to open, import, or save a file with
a particular format.



A document report is an FDK client that provides information about a document. The
user can start a document report by choosing Utilities>Document Reports from the
File menu and selecting the report from the Document Reports dialog box.

When FrameMaker starts, it reads the maker.ini file in the FrameMaker installation
directory, and if applicable, the maker.ini file stored in the user’s Documents and
Settings directory. The [APIClients] section of the maker.ini file contains entries
describing the FDK clients to be loaded. FrameMaker then scans the
fminit/Plugins directory and subdirectories and loads the FDK clients that have a
.dll file extension and valid VERSIONINFO resource information. FrameMaker
ignores all other files in the fminit/Plugins directory that do not have a .dll file
extension and valid VERSIONINFO resource information.

20

FDK Programmer’s Guide

Writing FDK clients for Windows

...

G e t t i n g St a r t e d w i t h F D K 1 2

Writing FDK clients for Windows
How to write an FDK client for Windows
When you write an FDK client, you should do the following for it to compile and run
correctly on Windows:


Include the correct FDK header files in the correct order



Replace platform-specific functions and data types with FDE equivalents



Include calls to initialize the FDE if your client calls FDE functions

The following sections discuss these tasks in greater detail.

Including FDK header files
The following table lists the header files you must include in your client in the order in
which you must include them.
If you are using

Include

Any FDK function or constant

fapi.h

Any FDE type

fdetypes.h

A specific FDE function

Header file for the function’s group (for example,
fhash.h for a hash function). For more
information, see the function’s description in the
FDK Programmer’s Reference.

Any Structure Import/Export API

fm_struct.h

functions
Constants for Frame f-codes

fcodes.h

..............................................................................

IMPORTANT: You must include the fapi.h header file before any other FDK header
files. For example, if your client uses API functions and FDE metric utility functions, it
must include header files as follows:
..............................................................................

#include "fapi.h"
#include "fdetypes.h"
#include "fmetrics.h"

If you need to include any C library header files or your own header files, include them
before the FDK header files.

FDK Programmer’s Guide

21

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing FDK clients for Windows

Adding calls to initialize the FDE
If your client calls FDE functions, it must call F_FdeInit() once before it calls the
functions. The syntax for F_FdeInit() is:
ErrorT F_FdeInit(VoidT);

To call F_FdeInit(), your client must include the fdetypes.h header file.

How to write filter clients
You can use filter clients to translate documents from one format to another.
FrameMaker invokes an import filter client when it recognizes a file of a particular
format or when the file has a registered suffix. It invokes an export filter when you
choose a particular format from the Format pop-up menu of the Save As dialog box or
save a file using a registered suffix. For example, if you register a suffix for a text import
filter and then open a file with that suffix, the Unknown File Type dialog box appears
with the appropriate filter preselected.
You must register your filter client before use. For information on registering clients,
see "Compiling, Registering, and Running FDK Clients".
You can also use your filter to import text or graphic files into a document. If you import
a file by reference, FrameMaker stores in the document the registered format and
vendor ID of the filter used in the import operation. If you import the file by copy,
FrameMaker stores the facet name in the document. The information in both these cases
ensures that FrameMaker invokes the correct filter for updating the next time you open
the document.
..............................................................................

IMPORTANT: If you are writing a filter client, FrameMaker will not fully recognize it
unless you include function calls that actually cause the API library to link with your
client. To make sure the client links properly, you can include the following as minimal
code in your F_ApiNotification() function:
..............................................................................

. . .
F_ObjHandleT docId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);

Identifying your filter
To identify your filter to FrameMaker, you need to supply information in the line that
registers the filter. This information identifies the filter on all platforms and identifies
the original import filter when reimporting the file. FrameMaker uses several pieces of
information that you specify for this purpose:


22

FDK Programmer’s Guide

The vendor ID is a four-character string describing the provider of the filter.

Writing FDK clients for Windows

...

G e t t i n g St a r t e d w i t h F D K 1 2



The format ID is a four-character string describing the file format of files on which
the filter operates.



The facet name is an arbitrary-length string describing the filter.

For example, assume you create a filter for Windows machines that translates
Himyaritic documents to English. You give it the format ID "HIMF" and the vendor ID
"FAPI". If you create a document and create a text inset using that filter, FrameMaker
stores this information with the inset. The next time you open that document,
FrameMaker knows to update the inset with your Himyaritic filter.
FrameMaker reserves the following vendor IDs:


"FRAM"



"FFLT"



"IMAG"



"XTND"



"AW4W"



"ADBE"



"ADBI"

Your client cannot use these vendor IDs. FrameMaker recognizes FAPI as a valid ID for
anyFDK filter client. However, you do not have to use this ID. You can use any other
four-characterstring as your vendor ID.
FrameMaker reserves format IDs for the indicated file formats. For a complete list of
format Ids, see "Specifying format IDs and filetype hint strings". FrameMaker does not
supply filters for all of these formats. However, to aid in portabilityof your clients, you
should not use one of these format IDs unless it is for the specified file format.
Automatic recognition of a file format
Some graphic file formats have signature bytes. Signature bytes are a set of bytes that
have a unique value and location in a particular file format. FrameMaker can use
signature bytes to identify a graphic file’s format.
The documentation for the file format that your graphics filter converts may contain
information on the signature bytes for that format. If it does, you can register the
signature bytes in the [FormatList] section of the maker.ini file. Each graphic file
format description must be on a separate line and must have the following format:
n=facet_name start_offset signature_size signature

where n is any number, facet_name is the file format’s description (also used in the
client registration), start_offset is how many bytes from the start of the file the
signature begins, signature_size is the size in bytes of the signature, and
signature is the hexadecimal value of the signature. You can enclose any of the
FDK Programmer’s Guide

23

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing FDK clients for Windows

arguments in double quotation marks. For example, you can register the file format for
MIF with the following:
[FormatList]
100="MIF" 0 8 0x3c4d494646696c65

where 0x3c4d494646696c65 is the hexadecimal encoding of the characters
MIFFile.

Using Windows pathnames
The FDK delimits pathnames with backslashes (\). When you specify a pathname in an
FDK function call, follow these rules:


Follow the drive letter with a colon.



Don’t terminate a pathname that specifies a file with a backslash.

The following table lists examples of files and directories and the pathname strings that
specify them.
File or Directory

Absolute Pathname

Relative Pathname

File named myfile.doc on the

c:\myfile.doc

myfile.doc

c:\mydir

mydir

c: drive
Directory named mydir on
the c: drive

Because the backslash is a special character, you must precede it with another backslash
when you specify it in a string. For example, to open a file named c:\myfile.doc with
F_ApiSimpleOpen(), use the following code:
F_ApiSimpleOpen("c:\\myfile.doc", False);

Using pathnames returned by FDK functions
Pathnames returned by FDK functions don’t end with a backslash, unless they specify
rootdirectories, such as c:\.
Using F_PathNameToFilePath()
To specify an absolute pathname when you call F_PathNameToFilePath(), you
must specify a pathname that includes the drive and begins with the root directory of the
drive. If the pathname does not include the drive and begin with the root directory of the
drive, F_PathNameToFilePath() assumes the pathname is relative.
If you call F_PathNameToFilePath() with anchor set to NULL and you do not
specify an absolute pathname, F_PathNameToFilePath() adds the currently open

24

FDK Programmer’s Guide

Writing FDK clients for Windows

...

G e t t i n g St a r t e d w i t h F D K 1 2

directory or the currently open directory of the specified drive to the pathname. For
example, if you specify c:myfile.c for pathname, F_PathNameToFilePath()
generates: c:\cwd\myfile.c, where cwd is the currently open directory on drive c:.
If you specify \\myfile.c for pathname, F_PathNameToFilePath() generates:
current_drive:\myfile.c, where current_drive is the current drive.
If you do not set anchor to NULL, F_PathNameToFilePath() constructs the
filepath relative to the path specified by anchor. If the pathname you specify for
pathname and the filepath you specify for anchor are inconsistent,
F_PathNameToFilePath() ignores anchor and constructs the filepath with the
currently open directory
Using F_FilePathGetNext()
The function F_FilePathGetNext() returns the next file in a specified directory. To
do so, this function uses DOS system calls. As a result, since DOS is case-insensitive,
the returned FilePathT structure uses only uppercase letters. This may not match a
FilePathT structure you have created.

FDK Programmer’s Guide

25

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing FDK clients for Windows

For example, assume you want to create a filepath and then at some later time process
all files in the same directory other than the one you created. You might be tempted to
use this code:
/* Bad code! */
. . .
/* Create the new filepath */
newpath = F_PathNameToFilePath ("vpg.doc", NULL, FDosPath);
. . .
DirHandleT handle;
FilePathT *path, *file;
IntT statusp;
pathname = StringT;
handle = F_FilePathOpenDir(newpath, &statusp);
if (handle) {
pathname = F_FilePathToPathName (newpath);
while ((file = F_FilePathGetNext (handle, &Statusp)) != NULL) {
/* WRONG! This attempts to compare current file to the one you
created. */
if ! (F_StrEqual (pathname, F_FilePathToPathName (file)))
ProcessFile (file);
F_FilePathFree (file);
}
}
/* Bad code! */
. . ..

The string returned by F_FilePathToPathName(newpath) contains the lowercase
letters as specified in the earlier call to the function F_PathNameToFilePath(). On
the other hand, the string returned by each call to F_FilePathToPathName() always
contains only uppercase letters. Therefore, the call to F_StrEqual() never succeeds.
Instead of calling F_StrEqual(), you should call F_StrIEqual().

Using menus and commands
The following sections describe how to use menus and commands in your FDK client.

26

FDK Programmer’s Guide

Writing FDK clients for Windows

...

G e t t i n g St a r t e d w i t h F D K 1 2

Finding FrameMaker menu and command names
The [Files] section of the maker.ini file specifies the location of the menu and
command configuration files that list FrameMaker’s menus and commands. The
following are the default entries in the maker.ini file:
MathCharacterFile = fminit\mathchar.cfg
ConfigCommandsFile = fminit\cmds.cfg
MSWinConfigCommandsFile = fminit\wincmds.cfg
ConfigMathFile = fminit\mathcmds.cfg
ConfigMenuFile = fminit\maker\menus.cfg
ConfigCustomUIFile = fminit\customui.cfg

The following table lists the menus and commands each file contains.
Menu or Command File

Contents

MathCharacterFile

Special math characters

ConfigCommandsFile

Basic commands

MSWinConfigCommandsFile

Windows-specific commands

ConfigMathFile

Math commands

ConfigMenuFile

Standard menus

ConfigCustomUIFile

Custom menus

Using FDK functions that write to FrameMaker console
The following functions write output to the FrameMaker console on Windows:


F_ApiPrintFAErrno()



F_ApiPrintOpenStatus()



F_ApiPrintPropVals()



F_ApiPrintSaveStatus()



F_Printf() with Channel set to NULL



F_Warning()

For descriptions of these functions, see the FDK Programmer’s Reference. As with
printf(), the F_Printf() function does not automatically print a line feed ("\n")
after the output. If you don’t end the output with "\n", the next call to one of the
functions listed above begins printing on the last line printed by the F_Printf() call.

FDK Programmer’s Guide

27

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

Using platform-dependent session properties
Session (FO_Session) objects have the following platform-dependent properties:
Property

Value

FP_FM_BinDir

Pathname of the bin directory in the FrameMaker installation
directory

FP_FM_CurrentDir

Pathname of the FrameMaker installation directory

FP_FM_HomeDir

Pathname of the FrameMaker installation directory

FP_FM_InitDir

Pathname of the fminit directory in the FrameMaker
installation
directory

FP_HostName

Host name specified for PCName in the maker.ini file

FP_OpenDir

Pathname of the FrameMaker installation directory

FP_Path

Path specified by the $PATH environment variable

FP_TmpDir

Directory specified by the $TEMP environment variable

FP_UserHomeDir

Pathname of the FrameMaker installation directory

FP_UserLogin

The user name under which FrameMaker is registered

FP_UserName

The user name under which FrameMaker is registered

Although the values of some of these properties specify directory pathnames, they are
not terminated with a backslash.

Compiling, Registering, and Running FDK Clients
This section describes how to compile, register, and run FDK clients on Windows. It
also briefly explains how to debug your FDK clients.

Compiling FDK Clients
The following sections describe how to compile FDK sample clients and your own
clients.
Supported compilers
To compile FDK clients for Windows, you must use Microsoft Visual Studio 2010.

28

FDK Programmer’s Guide

Compiling, Registering, and Running FDK Clients

...

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling and registering sample clients in Microsoft Visual Studio 2010
To compile and register a sample FDK client in Microsoft Visual Studio 2010, follow
these steps:
1. Start Microsoft Visual Studio 2010
2. Open the Project and then choose the solution file for one of the sample clients.For
example, to compile the aframes sample client, choose
fdk_install_dir\samples\aframes\aframes.sln, where
fdk_install_dir is the pathname of the directory in which the FDK is installed.

NOTE: The project settings for the sample clients have relative paths to the FDK lib and
include files already specified. If you open a sample project from its location in the FDK
installation, these paths will be valid. If you move the sample client to a different
location, you may need to specify new paths for the include and lib files. For more
information, see "Compiling and registering your own FDK clients".
3. Use the build utility to build the client. Choose Rebuild Solution from the Build
menu. Microsoft Visual Studio 2010 compiles your code into a DLL file named
project.dll in the debug subdirectory of your client directory, where project is
the name of the sample project. For example, the aframes sample client compiles
into debug\aframes.dll.
4. Register the sample client.
Each of the following sample clients includes a VERSIONINFO resource, and you
register each by placing the DLL file in the Plugins folder:


pickfmts



elemutils



dialog

Because the remaining sample clients do not include a VERSIONINFO resource, you
must register them in the maker.ini file. For more information see "Registering clients
in the FrameMaker maker.ini file".
Running the sample FDK clients
It is best to store client DLL files in the FrameMaker Plugins folder
(install_dir\FrameMaker\fminit\Plugins), or in a folder below
it. If you register your clients via the VersionInfo resource, you must store them in
this way. When you register a client in the .ini file, you can specify any location for
the DLL file.
After you have compiled and registered a sample FDK client, start FrameMaker to test
the client. Some of the sample clients add menus and commands to the FrameMaker
menus. For example, if you have compiled and registered the sample client described in

FDK Programmer’s Guide

29

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

"Introduction to the Frame API", a menu named API appears on the FrameMaker menu
after you start FrameMaker. To test the commands on this menu, open or create a
document, and choose each of the commands.

Compiling and registering your own FDK clients
To compile and register one of your own FDK clients, follow the instructions in this
section.
Compiling and registering the client
To compile and register the FDK client, follow these general steps:
1. Create a project directory for your FDK client project.
2. Start Microsoft Visual Studio 2010 and create a new Win32 Dynamic- Link Library
project.
Choose New and then project from the File menu. The New dialog box appears. Select
Visual C++ Projects and then Win32 from Project Types. Select Win32 Project, type
your client's name in the Name field and then click OK. Win32 application wizard
appears.
Click on Application Settings, select DLL from Application Type and Empty project
from Additional Options.
3. Create or place your source files in the project directory, then add those files to your
project.
4. (Optional) Create a resource for any custom dialog boxes. If your client contains
custom dialog boxes, you need to create a resource for them. For instructions, see
"Handling Custom Dialog Box Events".
5. (Optional) Create a VERSIONINFO resource. Including a VERSIONINFO resource
is one method for registering a client. For more information on registering clients,
see "Registering FDK Clients".
6. Choose Properties from the Project menu to display the Properties Pages dialog box.
In the Properties Pages dialog box, choose General . Set Use of MFC field to Use
Standard Windows Libraries.
..............................................................................

IMPORTANT: If you don’t set the Use of MFC field to "Use Standard Windows
Libraries", your client will not link correctly.
..............................................................................

7. Set your project’s C/C++ Language options.
In the Property Pages dialog box, choose C/C++.

30

FDK Programmer’s Guide

Compiling, Registering, and Running FDK Clients

...

G e t t i n g St a r t e d w i t h F D K 1 2

Choose Code Generation and choose 8 Byte or default from the Struct Member
Alignment pull down menu. 8 bytes is also the default value for this field.
..............................................................................

IMPORTANT: If you don’t set the Struct Member Alignment to 8 Bytes, your client may
cause unexpected runtime errors.
..............................................................................

With Code Generation still selected, choose Single-Threaded from the Runtime Library
popup list. The FDK ships in a single-threaded version. By default, the project sets this
option to Multi-threaded. Compiling the FDK with a multi-threaded runtime library
produces the following warning:
defaultlib "LIBC" conflicts with use of other libs;
..............................................................................

IMPORTANT: For Version 7.0 and later of the FDK, it is important that you make this
setting. Earlier versions of the FDK did not use symbols that conflicted with the multithreaded runtime library. However, for version 7.0 and later the FDK and the Structure
Import/Export API use conflicting symbols.
..............................................................................

In the General page under C/C++ language options, add path to the FDK include files in
Additional Include Directories field. You can specify an absolute path or a relative path.
For example, the Property Pages for the sample clients all use the following relative
path:
..\..\include

8. Set your project’s Linker options:
In the Property Pages dialog box, choose the Linker page.
Choose General and then Input.
Add the FDK libraries fdk.lib, api.lib, and fmdbms32.lib to the additional
dependencies field.
If you are compiling a structure import/export client, be sure to also link the Structure
Import/Export API library. For more information, see "Linking the Structure
Import/Export API library".
..............................................................................

IMPORTANT: If your client includes custom dialog boxes, you must add
/section:.rsrc,w to the Project Options. For more information, see “"Compiling clients
with custom dialog boxes"”.
..............................................................................

In the Category field, choose Input, then add the path to the FDK lib files in the
Additional library path field.

FDK Programmer’s Guide

31

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

You can specify an absolute path or a relative path. For example, the project settings for
the sample clients all use the following relative path:
..\..\lib
As an alternative, you can specify access to the FDK include and lib directories for the
Development Environment 2003. To do this, choose Tools > Options to display the
Options dialog box. Select Project and then VC++ Directories, and enter the paths to the
FDK include and lib directories for Include files and Library files.
9. Use Microsoft Visual Studio 2010 build utility to build your client.
Choose Rebuild All from the Build menu. Visual Studio compiles your code into a
dynamic link library file with the name you typed in the New dialog box. It puts this
library file into the debug subdirectory of your client directory.
10. Register the client.
You can register the client by using either of these two methods:


As mentioned in step 5, create and include in your client’s project a VERSIONINFO
resource that contains information about the client, and copy or move the compiled
client into the fminit/Plugins directory.



Add an entry for your client in the [APIClients] section of the maker.ini file
inthe FrameMaker directory.

For more information on registering clients, see "Registering FDK Clients".

Using custom dialog boxes
The FDK samples include a template document for designing custom dialog boxes. You
open this document in FrameMaker and edit it with the FrameMaker graphic tools and
commands.
When you save a custom dialog box in a Windows version of FrameMaker, it generates
two Windows resource definition files, a .dlg file and a .xdi file.


The .dlg file is a text file containing resource statements. These statements are
standard Windows descriptions of the dialog box and its controls.



The .xdi file is a text file containing a user-defined resource statement. This
statement contains data used by FrameMaker to manipulate the dialog boxes.

When creating the .dlg and .xdi files, FrameMaker uses the name of the .dre file
(without the extension) to name the files and the actual dialog resource. For example,
when saving the file named mydlg.dre, FrameMaker creates the resource description
files mydlg.dlgand mydlg.xdi. Both files describe the dialog resource named
mydlg.
To compile the .dlgand .xdifiles in your dll you must create a resource for the
project, and provide directives to include these files in the resource. In the process of
32

FDK Programmer’s Guide

Compiling, Registering, and Running FDK Clients

...

G e t t i n g St a r t e d w i t h F D K 1 2

compiling the client, these resource definition files are compiled into a single resource
file (.rc). This resource file is linked to your client. To set up the resource definition
files to be compiled, follow these general steps:
1. Start Microsoft Visual Studio 2010.
2. If one doesn’t already exist for the project, create a resource script. Choose Add New
Item from the File menu. The Add New Item dialog box appears. Choose Resource
File.
3. Include the resource description files generated by FrameMaker.
Choose Resource Includes from the Edit menu. The Resource Includes dialog box
appears.
In the Compile-Time Directives field, type #include statements to include the resource
description files. For example, suppose you create two custom dialog boxes named
pgftag.dre and chartag.dre. When FrameMaker saves these files it also creates
the files pgftag.dlg, pgftag.xdi, chartag.dlg, and chartag.xdi.
To include these files in the resource script, type the following in the Compile-Time
Directives field:
#include "pgftag.dlg"
#include "pgftag.xdi"
#include "chartag.dlg"
#include "chartag.xdi"

Compiling clients with custom dialog boxes
If your FDK client uses custom dialog boxes, you need to specify a special link option
before compiling it:
1. In Micrsoft Visual Studio, choose Project->Properties. This displays the Project
Properties dialog box.
2. Choose Linker and then Command Line.
3. Add the following option to the Additional Options field:
/section:.rsrc,w
This link option makes the dialog resources writable. If you do not specify it before
compiling, your DK client may exit unexpectedly when it attempts to display a custom
dialog box.
4. Repeat steps 3 for each target in your project.
Making adjustments to custom dialog boxes
Since the .dlg files produced by FrameMaker are text files containing resource
statements, you can open these files as resources. You can use the built-in tools for

FDK Programmer’s Guide

33

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

dialog editing to view, adjust, and test the dialog box. Because you are modifying the
.dlg file but not the .xdi file, you should not make major changes to the dialog box
(for example, do not add new items to the dialog box). If you do, the description in the
.dlg file will not match the description in the .xdi file.

Linking the Structure Import/Export API library
To link the Structure Import/Export API library on Windows follow these steps:
1. In Microsoft Visual Studio 2010, open your client’s project.
2. Choose Properties from the Project menu to display the Properties Pages dialog box.
3. In the Property Pages dialog box, click on Linker and then Input.
4. Add the Structure Import/Export API library struct.lib and the resource
fmstruct.res to the Additional Dependencies field. Add struct.lib before
fdk.lib, and add fmstruct.res to the end of the Object/Library Modules field.
5. Add the following link option to the 'Additional Options' field in 'Command Line'
property page:
/section:.rsrc,w
..............................................................................

IMPORTANT: This link option is required for some of the dialog boxes that are internal
to the structure import/export functionality in FrameMaker. Without this link option,
your client may crash when it interacts with these dialog boxes.
..............................................................................

Registering FDK Clients
For FrameMaker to recognize your client, you must register it on the system on which
you intend to run it. When registering your client, you can name it anything you like,
although the name cannot contain spaces. Also, you should not use a name that is
already used by one of the clients that ships with FrameMaker.
To register your client, you add an entry for your client in the [APIClients] section of
the maker.ini file in the FrameMaker directory. The [APIClients] section of the
maker.ini file lists the FDK clients to load when FrameMaker starts. For more
information on registering your client using the maker.ini file, see "Registering clients
in the FrameMaker maker.ini file".
Registering clients in the FrameMaker maker.ini file
You can register a client is by adding an entry for the client in the FrameMaker
maker.ini file. The [APIClients] section of the maker.ini file lists the FDK clients

34

FDK Programmer’s Guide

Compiling, Registering, and Running FDK Clients

...

G e t t i n g St a r t e d w i t h F D K 1 2

to load when FrameMaker starts. Each client description must be on a separate line and
cannot contain line breaks. Clients that are not filters use the following format:
client = type, description, DLL_file, mode

where
For this statement

Specify

client

the client’s name

type

the type of client—valid types for clients other than filters
are Standard,TakeControl, and DocReport

DLL_file

the pathname of the client’s DLL file—can specify a full
pathname or a relative pathname based on the FrameMaker
installation directory.

mode

whether the client can run with FrameMaker in unstructured
or structured mode. This fields can be one of maker,
structured, or all. The mode field is required.

The fields in this line are separated by a comma and zero or more spaces. For example,
if you have compiled the aframes sample client into
c:\fdk\samples\aframes\debug\aframes.dll, and you want to register it
with FrameMaker, add the following to the maker.ini file in the FrameMaker
installation directory (without any line breaks):
AFrames=DocReport,Anchored Frames Report,c:\fdk\samples\aframes\
debug\aframes.dll, all

If the client is a filter, register it with the following line:
client = type, facet_name, format_id, vendor_id, display_name,
description, DLL_file, mode, suffix

where the variables are:

FDK Programmer’s Guide

35

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

For this statement

Specify

type

One of:
● TextImport
● GFXImport
● Export
● FileToFileTextImport
● FileToFileTextExport
● FileToFileGFXImport
● FileToFileGFXExport

facet_name

the name of the file format supported by the client.

format_id

a four-character string that identifies the file format

vendor_id

a four-character string that identifies the client’s provider

display_name

the filter name to display in in dialog boxes when opening
or saving a file of the given format. This name must match
the client name.

description

a description of the client that appears when you choose
About

DLL_file

the pathname of the client’s DLL file

mode

whether the client can run with FrameMaker in
unstructured or structured mode. This fields can be one of
maker, structured, or all. The mode field is required.

suffix

the filename extension of the file type that the client filters

For information on format and vendor IDs, see "How to write filter clients". For
example, assume you have a graphics import filter for the CGM format that uses ACGM
as its facet name, has its executable stored in acgmflt.dll, and should be invoked on files
with the suffix cgm. You can register this filter with this line:
ACGMFILTER=GFXImport,ACGM,CGM,FAPI,ACGMFILTER,acgmflt.dll,all,
cgm

Specifying no description for a client
When you register your client by using the FrameMaker maker.ini file, and you don’t
want to specify a description, enter a space in the description field. For example:
client= Standard, ,c:\clients\myclient\debug\myclient.dll, all

36

FDK Programmer’s Guide

Compiling, Registering, and Running FDK Clients

...

G e t t i n g St a r t e d w i t h F D K 1 2

The description field must contain at least one character. If no characters appear
between the commas delimiting the description field, your client will not be registered.

Running FDK Clients
When FrameMaker starst, it reads the maker.ini file. The [APIClients] section of
the maker.ini file contains entries describing the FDK clients to be loaded.
FrameMaker then scans the fminit/Plugins directory and subdirectories and loads
the FDK clients that have a .dll file extension and valid VERSIONINFO resource
information.
FrameMaker ignores any files in the fminit/Plugins directory and subdirectories
that do not have a name with the .dll extension, or do not contain valid
VERSIONINFO resource information.
For information on how FrameMaker starts a client, see "API Client Initialization” in
the FDK Programmer’s Guide.

Compatibility between FDK and FrameMaker product releases
To ensure your existing Windows clients are compatible with release 11 of
FrameMaker, you should recompile them. It is possible to run a a client compiled in an
earlier version of the FDK with FrameMaker 11, as long as the client does not use any
functions or properties that have changed. However, it is recommended that you
recompile your clients with the newer version of the FDK as soon as possible.

Disabling FDK clients
To disable all FDK clients, edit the following line in the maker.ini file in the
FrameMaker installation directory, or in the version of the .ini file that is stored in the
user’s Documents and Settings directory:
API=On

Replace On with Off. The next time you start FrameMaker, no FDK clients will be
started.
..............................................................................

IMPORTANT: Some FrameMaker features, such as the Word Count document report,
Save As HTML, or import and export of XML are implemented as FDK clients. If you
disable all FDK clients, these features will not be available.
..............................................................................

FDK Programmer’s Guide

37

5

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling, Registering, and Running FDK Clients

Debugging FDK Clients
You debug your client as part of the FrameMaker executable. The FrameMaker
executable is not compiled with debugging information, so you don’t have access to any
symbols within FrameMaker.
To use Microsoft Visual Studio to debug your client as part of the FrameMaker
executable, follow these general steps:
1. Start Microsoft Visual Studio 2010.
2. Open your client’s project and add breakpoints.
3. Select Project->Properties and then Debugging page. Go to Command Field and add
the path to FrameMaker executable.pen the FrameMaker executable.
For example, if FrameMaker is installed in
c:\Program Files\Adobe\FrameMaker10,

then to open its executable, open
c:\Program Files\Adobe\FrameMaker10\FrameMaker.exe.

4. From the Build menu select Configuration Manager. Highlight the Debug Project
Configuration.
5. From the Debug menu, choose Start. Alternately, if you have already started the
debugger for your program, from the Debug menu choose Restart. If FrameMaker
isn’t able to load your client, it displays the following error message in an alert box:
File Error: Cannot find client_name.dll

FrameMaker may not be able to load your client for the following reasons:


The client is not located in the fminit/Plugins directory or subdirectories, or does not
have a name with the .dll extension.



The client’s VERSIONINFO resource information is missing or invalid.



The maker.ini file doesn’t specify the correct full pathname for your client’s DLL.



The FrameMaker release is incompatible with the FDK release that you used to
compile the client.

To check that your FDK client has control, you can have it display a string in the status
bar of the document or book window. For more information, see the descriptions of
FO_Book and FO_Doc in the FDK Programmer’s Reference.

38

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client
This section describes how to create asynchronous clients on Windows, and provides
instructions for compiling and running a sample asynchronous client. Before writing an
asynchronous API client you should be familiar with both the FrameMaker FDK
andWindows API programming.
The purpose of many FDK clients is to modify FrameMaker in some way, such as by
changing or adding functionality. In these applications the main goal of the resultant
application is still for the end user to use FrameMaker.
A different kind of application is one that uses FrameMaker to support some aspect of
the application’s functionality, but in which use of FrameMaker is not the goal. For
example, you might create a data base and want to use FrameMaker to print catalogs
from it. In this case, your application runs primarily independently of FrameMaker, but
calls FrameMaker (possibly as a child process) during some part of its operation.
The FDK allow you to create asynchronous applications that control a FrameMaker
process. Even though the main purpose of the application may not be to run
FrameMaker, this chapter refers to such an application as an FDK client, since it calls
FDK functions.
An asynchronous client does not run as part of the FrameMaker process nor as a child
process. Instead, it is its own application in a separate process, communicating with a
FrameMaker process via Microsoft RPC (Remote Procedure Calls). You should be
aware of some consequences of this difference:


An asynchronous client can be started independently of any FrameMaker product. It
can be an EXE, or a DLL of some EXE other than FrameMaker.



It must have its own main() function.



You can use MFC or any other application framework to develop an asynchronous
client.



An asynchronous client can run on a machine other than that running the associated
FrameMaker process.

End user installations
To run asynchronous clients, the executable applications or the DLL files must be
installed correctly. An EXE can be installed wherever the user wants. A DLL that is a
plugin for another application must be installed correctly for that application. A DLL
that is a plugin for FrameMaker must be installed in the appropriate Plugins directory,
or its path must be specified in the maker.ini file.
The user also must have the following files installed in his or her FrameMaker
installation directory, at the same level as the FrameMaker application:

FDK Programmer’s Guide

39

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client



afmfdk.dll



fmrnclnt.exe

In addition, the user must have the following entries in the maker.ini file:
[Files]
MarshallingDLL = afmfdk.dll
RunWrappedPlugin = fmrnclnt.exe
. . .
[Preferences]
ExecutablePlugins = EXE
WrappedPlugins = DLX
PluginExtensions = DLL, DLX, EXE

The [Preferences] entries tell FrameMaker which filename extensions are valid for
different types of clients.


PluginExtensions must list extensions for all the files you want to be loaded as
clients of any type.



ExecutablePlugins lists extensions for clients that are built as executables
which run outside of the FrameMaker process.



WrappedPlugins lists extensions for clients that are built as DLLs, but will run in
an address space that is external to the FrameMaker process. Such a client uses
fmrnclnt.exe to wrap its DLL and runs in the fmrnclnt.exe address space.

Note that you can substitute other extensions for the ones shown in the example above.
For more information, see "Types of asynchronous clients".

Registering asychronous clients
You can register asynchronous clients just as you register other clients; you can store the
registration data in the client’s VersionInfo resource, or you can make an entry in the
maker.ini file for FrameMaker. Additionally, your client can pass an F_PropValsT
structure to F_ApiWinConnectSession() that is a list of registration data.
F_ApiWinConnectSession() is defined as:
F_ApiWinConnectSession(const F_PropValsT *connectProps,
ConStringT hostname, const struct _GUID *service);

You can include the following properties in connectProps:

40

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

corresponds to this statement in a client’s
VERSIONINFO resource

This property

FI_PLUGIN_NAME

the name of the client.

FI_PLUGIN_TYPE

the type of client

FI_PLUGIN_PRODUCTS s

specifies structured or unstructured FrameMaker, using the
names of FrameMaker products this client upports—use a
space-delimited string with one or both of Maker and

MakerSGML
FI_PLUGIN_FACET

the name of the file format supported by the client (filters,
only)

FI_PLUGIN_FORMATID

a four-character string that identifies a file format (filters,
only).

FI_PLUGIN_VENDOR

a four-character string that identifies the client’s provider.

FI_PLUGIN_SUFFIX

the filename extension of the file type that the client filters
(filters,
only).

FI_PLUGIN_INFORMAT

the file format for the file to filter (filters, only)

FI_PLUGIN_OUTFORMAT

the file format for the resulting file (filters, only)

FI_PLUGIN_DESCRIPTION

a description of the client that appears when you choose
About

FI_PLUGIN_PRODUCTNAME

the name by which customers know your client.

If connectProps is NULL, the FrameMaker process uses the client’s
VersionInfo resource or the entries in the maker.ini file. If the client has no
registration information in any of these sources, the FrameMaker process registers it as
a standard client.

Types of asynchronous clients
Asynchronous clients can be executable applications (EXE), dynamically linked
libraries (DLLs) that are a part of another application, or DLLs that are plugins for
FrameMaker (wrapped plugins).

FDK Programmer’s Guide

41

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

Asynchronous EXE applications
An EXE can be either a console application or a Windows application. After connecting
with the FrameMaker process, the EXE application passes calls to FrameMaker through
afmfdk.dll.
..............................................................................

IMPORTANT: Because they don’t have a Windows message processing loop, console
applications cannot handle notifications from the FDK. For example, this means a
console application cannot process commands from menus it adds to FrameMaker. Nor
can it process notifications such as FA_Note_PreOpenDoc or FA_Note_PreSaveDoc.
..............................................................................

Asynchronous DLLs
A DLL that is part of another application can call F_ApiStartUp() to make a
connection with a FrameMaker process. For example, you could write a plugin for
Acrobat Exchange that writes the data from Acrobat Forms to a FrameMaker document.
In that case, the DLL communicates with the FrameMaker process, as a part of its parent
EXE, via afmfdk.dll.
A DLL that runs as a wrapped plugin for FrameMaker runs in its own memory space.
After connecting with the FrameMaker process, the DLL invokes fmrnclnt.exe to
run as a wrapper for the DLL. The wrapped DLL then communicates with FrameMaker
via afmfdk.dll, as though it is an EXE.

Registering multiple FrameMaker processes as servers
When you first run FrameMaker, it registers istelf in the system registry as the default
instance of the FrameMaker instance on that machine. By default, asynchronous clients
connect to this instance.
You can register multiple instances of the FrameMaker process, each with a unique
entry in the system registry. Then you can use these processes as a bank of servers, and
your client can choose among them when making a connection.
You identify a FrameMaker process as a server by its entry in the system registry. The
entry can specify:


A name to identify the GUID for that specific process.



Whether the process starts up when called by a client, or whether it must already be
running before the client can connect to it.

To register a process, you start FrameMaker with specific commandline options. This
creates an entry in the system registry for the machine on which you start FrameMaker.
To start FrameMaker with commandline options:
1. Choose Run from the Start menu.
42

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

The Run Application dialog box appears.
2. In the text box, type the full pathname of the FrameMaker.exe file, followed by the
commandline options. Alternately, you can start FrameMaker from a DOS
Command Prompt window. For example, type
FrameMaker_path\FrameMaker10 /option, where FrameMaker_path is
the install path for the version of FrameMaker you want to run, and /option is one
or more of:


progid:process_name

where process_name is a name you provide. This option registers a name for the
FrameMaker process.


auto

This option allows the FrameMaker process to automatically start up if it isn’t running
when another process calls it.


noauto

This option disallows automatic start-up.
This creates an entry in the system registry for the machine on which you started
FrameMaker.

Registering a name for a FrameMaker process
To specify a name for the process, use the /progid option. For example, type
FrameMaker_path\FrameMaker10 /progid:MyProcess.Api1, where
FrameMaker_path is the install path for the version of FrameMaker you want to run.
This establishes a name, MyProcess.Api1, for the process.
When you start FrameMaker with no /progid option, you create system registry entry
with the default name of FrameMaker.API.1.
Asynchronous clients running locally on the host can refer to processes by their names.
In this way, your client can choose which process to run for a given task.
..............................................................................

IMPORTANT: Clients connecting to a remote host cannot use the process name to
connect to a FrameMaker process. Instead, they must use the GUID for that process, as
it is specified in the system registry.
..............................................................................

Registering automatic start-up for a process
If the FrameMaker process is not running, an asynchronous client can still call it. If the
process is so registered, it will start up when the client calls it. Alternatively, you can
register the process in a way that does not allow automatic start-up.
FDK Programmer’s Guide

43

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

To register the process for automatic start-up, use the /auto option. To disallow
automatic start-up, use the /noauto option. For example, type
FrameMaker_path\FrameMaker7.2 /progid:MyProcess.Api1 /auto,
where FrameMaker_path is the install path for the version of FrameMaker you want
to run. This establishes a process named MyProcess.Api1, which will start
automatically when an asynchronous client calls it.

Running asynchronous clients on remote hosts
With systems that support DCOM, you can run a client on one machine (the client
machine), connected to a FrameMaker process on another machine (the host machine).
To accomplish this, you make use of the DCOM services provided with your operating
system. Also, both machines must be in the same domain, and the same user must have
the accounts on both machines.
For an asynchronous client to connect to a FrameMaker process on a remote host:
1. Register the FrameMaker process as a server process on the host machine.
This establishes entries on the host machine’s system registry for the FrameMaker
processes you want to run as servers. For more information see “"Registering multiple
FrameMaker processes as servers".
2. Run dcomcnfg on the host machine to configure DCOM accessibility for each
process you want to run as a server.
This enables DCOM connections to the FrameMaker server processes that are
registered on the host machine.
3. Run dcomcnfg on the client machine to configure its DCOM accessibility.
This enables the client machine to connect to the host machine via DCOM.
Enabling DCOM for the server processes on the host
To enable DCOM for a FrameMaker process on the host machine:
1. Choose Run from the Start menu.
The Run dialog box appears.
2. In the Run dialog box, type dcomcnfg
The DCOM Configuration Properties service application appears.
3. Select the Default Properties tab and click Enable Distributed COM on this
Computer.
4. In the Applications list box, double-click the FrameMaker process you want to
enable, then set the appropriate security options.

44

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

5. Click the Security tab and make sure Use default configuration permissions is turned
on.
6. Apply any other settings to the FrameMaker process or your computer that are
appropriate for your network configuration. You should check with the system
administrator to ensure the options you set are compatible with his administration
procedures.
7. Click OK.
Enabling DCOM for client machine
To enable DCOM on the client machine:
1. Choose Run from the Start menu.
The Run dialog box appears.
2. In the Run dialog box, type dcomcnfg
3. The DCOM services application appears.
4. Select the Default Properties tab and click Enable Distributed COM on this
Computer.
5. Apply any other settings to your computer that are appropriate for your network
configuration.You should check with the system administrator to ensure the options
you set are compatible with the administration procedures.
6. Click OK.
To find more information on DCOM see the Windows Online Help.
Connecting with a FrameMaker process
Asynchronous clients connect with a FrameMaker process by calling
F_ApiStartUp() or F_ApiWinConnectSession(). When connecting to a process
on a local host, FrameMaker does not have to be registered as a server. For a process on
remote host, your client must know the GUID for that process.
A machine may have more than one FrameMaker process running at a time. In that case,
the processes must be registered as servers, and they should be registered with a name
for each process. For information about registering FrameMaker processes as servers,
see "Registering multiple FrameMaker processes as servers".
Asynchronous clients use COM to communicate with FrameMaker processes. If any
FDK call returns FE_Busy, then you probably need to register a message filter. When
using COM, an application should always register a message filter. If your code calls
F_ApiStartUp() or F_ApiWinConnectSession() before initializing COM, these
routines automatically initialize COM and register a message filter. However, if you
initialized COM before calling these routines, they assume your application already

FDK Programmer’s Guide

45

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

registered a message filter. If your application initializes COM but does not register a
message filter, be sure to call F_ApiWinInstallDefaultMessageFilter().

Connecting to the default process on a local host
You use F_ApiStartUp() when the desired FrameMaker process is running on the
local machine. For example, a DLL that is a FrameMaker plugin calls
F_ApiStartUp(). In that case, the FrameMaker process that invokes the DLL
identifies itself by passing a globally unique identifier (GUID) via the FMGUID
environment variable. Likewise, if you want an EXE to connect locally to the currently
active FrameMaker process, use F_ApiStartUp().
The following call makes this connection:
F_ApiStartUp(NULL);
For more information, see F_ApiStartUp() in the FDK Programmer’s Reference.

Connecting to a named process on a local host
To connect to a named process on a local machine, you need to convert the process
name to a GUID. Then you can pass that GUID to F_ApiWinConnectSession() to
initiate communication between your client and the FrameMaker process.
Note that F_ApiStartUp() makes a reliable connection only when the desired
FrameMaker process is the only FrameMaker process running on the local host. If no
FrameMaker process is running, F_ApiStartUp() will not work. Also, if more than
one process is running,
F_ApiStartUp() cannot determine which process will finally connect with your
client. To choose one of many FrameMaker processes on a local host, you should have
all of the processes registered as servers on that host.
If you have registered the process as a named server, and your client is connecting to it
on a local host, you can use the Win32 API to get the GUID associated with that name.
Then you pass the GUID to F_ApiWinConnectSession().
The following example uses the Win32 API function CLSIDFromProgID() to get the
GUID for a process named MyProcess.Api1. It then calls
F_ApiWinConnectSession() to connect to the process. Note that you need a

46

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

Unicode string for the process name. The example uses the Win32 API call,
MultiByteToWideChar() to convert a string to Unicode.
#define WBUFLEN 512
OLECHAR progStr;
CLSID serviceId;
StringT myProcess = F_StrCopyString("MyProcess.API.1");
. . .
progStr = (OLECHAR*)malloc( WBUFLEN*sizeof(wchar_t) );
MultiByteToWideChar(CP_ACP, 0, (char *)opt_progid, -1, progStr,
WBUFLEN );
if(CLSIDFromProgID(progStr, &serviceId))
F_ApiConnectWinSession(0, 0, &serviceId);
. . .

Note that F_ApiWinConnectSession() takes three parameters. In the first
parameter you can pass a list of properties that correspond to the entries you provide
when registering a FrameMaker client.
The second parameter is for the address of a remote host, when making a connection to
a remote host. If this parameter is NULL or 0, F_ApiWinConnectSession()
connects to the local host.
The third parameter specifies the desired FrameMaker process on the host machine. If
this parameter is NULL or 0, F_ApiWinConnectSession() uses the value of the
FMGUID environment variable on the specified host.
For more information, see F_ApiWinConnectSession() in the FDK Programmer’s
Reference.

Connecting to a remote host
To connect to a remote machine, you need the address of that machine. Once you have
the address, you can call F_ApiWinConnectSession() to initiate communication
between your client process and the FrameMaker process on the host machine. The
following call makes this connection to the currently running FrameMaker process on
the remote host:
F_ApiWinConnectSession(0, remote, 0);

where remote is the address of the remote host.
The above call only works when the desired FrameMaker process is the only
FrameMaker process running on the remote host. If no FrameMaker process is running,
this will not work. Also, if more than one process is running, you cannot predict which
process will finally connect with your client.

FDK Programmer’s Guide

47

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

To choose one of many FrameMaker processes on a remote host, you should have all of
the processes registered as servers on that host.
To choose a registered process, you must know the GUID for that process ahead of time;
you pass that GUID to F_ApiWinConnectSession(). Assuming you have specified
a GUID in serviceId, the following call connects to a specific process on the remote
host:
stringT remote;‘
CLSID serviceId;
. . .
F_ApiWinConnectSession(0, remote, &serviceId);

where remote is the address string of the machine that is running the FrameMaker
process.

How to write an asynchronous FDK client
To write an asynchronous client that communicates with FrameMaker, you proceed as
you would for any C application, providing a main() function and adding whatever
functionality you need.
A Windows client can get control of a FrameMaker process by invoking
F_ApiCallClient() to call itself. For the duration of the notification, that is while
the client is processing the resulting callback, the client has exclusive control of
FrameMaker. At some point in its processing, your client needs to communicate with a
FrameMaker process. To do so, it follows these general steps:
1. Connect to the FrameMaker process.
To connect to a local host, use F_ApiStartUp() or F_ApiWinConnectSession().
To connect to a remote host, use F_ApiWinConnectSession(). For information
about connecting to FrameMaker processes, see "Connecting with a FrameMaker
process". For information about the functions to connect to FrameMaker processes, see
F_ApiWinConnectSession() and F_ApiStartUp() in the FDK Programmer’s
Reference.
2. Depending on your client, wait for requests from FrameMaker or perform some
operations using FrameMaker.
Once connected to a running FrameMaker process, your client can use the FDK to
control the FrameMaker process, or receive notifications from it. However, bear in mind
that console programs cannot handle notifications from the FDK. (This is because
console programs do not have a Windows message processing loop; applications
running in console programs must not request notifications.)

48

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

Note that a client can take exclusive control of the FrameMaker process by requesting
notification for FA_Note_ClientCall and then calling itself via
F_ApiCallClient().
While handling the notification, no other clients can take control of the FrameMaker
process.
3. When done, disconnect from the FrameMaker process.
How your client disconnects depends on the situation. With a client that is a plugin for
FrameMaker, you can call F_ApiBailOut() to terminate the client. After calling
F_ApiBailOut(), the client’s notification points are still registered with the
FrameMaker process. If a notification event occurs, the FrameMaker process restarts
the client by calling F_ApiInitialize() with initialization set to
FA_Init_Subsequent. When it starts up subsequently, the client’s global variable
settings are lost.
If the FrameMaker process still exists when your client is completely done
communicating with it, your client should call the function
F_ApiDisconnectFromSession() to break the RPC connection.
Alternatively, the FrameMaker process may have shut down when your client wants to
break the connection (for example, due to a user request or due to a command from your
client). If so, your client should call the function F_ApiShutDown() to close its side
of the RPC connection.

FDK Programmer’s Guide

49

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

Writing a Main routine in Windows.
Windows does not provide a default main routine for remote plugins. You must provide
your own main routine. Simply include the following lines in your client:
#define DONT_REDEFINE /* We need to use native types. */
#include ‘fapi.h’
#include 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR
lpCmdLine, int nCmdShow)
{
return F_ApiRun();
}
The routine F_ApiRun() is documented in the FDK manuals and is
implemented as follows:
IntT
F_ApiRun(VoidT)
{
ConStringT s = F_ApiStartUp(NULL);
if (s)
F_ApiErr(s);
else
while (!FA_bailout)
F_ApiService(NULL);
F_ApiShutDown();
return s !=NULL;
}

F_ApiStartup() and F_ApiService() ignore their parameters and should be
passed NULL.
It is not necessary to call F_ApiRun(). You may choose to implement your main
routine using these primitives directly. If your program has a windows message loop
you need only call F_ApiStartup(NULL).
However if your remote plugin does not call F_ApiRun(), it must either periodically
check the FA_bailout flag or arrange to terminate based on the
FA_NotePostQuitSession notification. You must make these checks, otherwise
FrameMaker can terminate leaving your client running.

50

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

Compiling and running a sample client
The following code sample is a console application that connects to the default
FrameMaker session and gets the name of the active FrameMaker document. Following
the code is a lineby-line description of how it works.
1. #define DONT_REDEFINE // Console app needs native types
2. #define WBUFLEN 512
3.
4. #include "fdetypes.h"
5. #include "futils.h"
6. #include "fapi.h"
7. #include "fstrings.h"
8. #include 
9. #include  //not required
10. #include  //not required
11.
12. int main(int argc, char **argv)
13. {
14.

StringT opt_progid;

15.

CLSID pclsid;

16.

LPOLESTR progStr;

17.

HRESULT res;

18.

F_ObjHandleT docId;

19.
20.

// Get the process name.

21.

if(argc == 2)

22.
23.

opt_progid = F_StrCopyString((StringT)argv[1]);
else {

24.

fprintf(stderr, "You must provide a process name.");

25.

return(1);

26. }
27.
28.

// Convert the process name into a GUID

29.

progStr = (OLECHAR*)malloc( WBUFLEN*sizeof(wchar_t) );

30.

if(0 == MultiByteToWideChar(CP_ACP, 0,
(char *)opt_progid, -1, 31. progStr, WBUFLEN )) {

32.

fprintf(stderr, "failed to allocate\n");

FDK Programmer’s Guide

51

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

33.

return(1);

34.

}

35.

if (progStr[0] == '{') // hex-codes within brackets

36.
37.

res = CLSIDFromString(progStr, &pclsid);
else

38.

res = CLSIDFromProgID(progStr, &pclsid);

39.
40.

if(res == S_OK)

41.
42.

F_ApiWinConnectSession(NULL, NULL, &pclsid);
if (!F_ApiAlive()) {

43.

fprintf(stderr, "No connection: %s\n", opt_progid);

44.

return 1;

45.

}

46.

// Print the name of the current document.

47.

docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);

48.

if (docId) {

49.

StringT docname = F_ApiGetString(FO_Session, docId,
FP_Name);

50.

fprintf(stderr, "Current document: %s\n", docname);

51.
52.

F_ApiDeallocateString(&docname);
} else

53.

fprintf(stderr, "No active document\n");

54.
55.

return 0;

56. }

Line 1
To compile this client as a console application, you need to use types that are native to
the C language. This statement keeps the FDE from redefining those types.
Lines 20–26
These lines parse the commandline options you pass to the client when you invoke it.
You invoke the exe with the name of a FrameMaker process as an argument. To run the
default process, use the name FrameMaker.API.1. For example, assuming the exe is
named fmRemote.exe, type the following to invoke it with the default FrameMaker
process: fmRemote.exe FrameMaker.API.1
For more information, see "Registering a name for a FrameMaker process".

52

FDK Programmer’s Guide

Writing an Asynchronous FDK Client

...

G e t t i n g St a r t e d w i t h F D K 1 2

Lines 28–38
These lines convert the process name into a valid GUID. Note that you need a Unicode
string for the process name. The code uses the Win32 API call,
ultiByteToWideChar() to convert the process name to Unicode. It then uses the
Win32 API functions CLSIDFromProgID() or CLSIDFromString() to get the
GUID for the specified process.
Lines 40–45
If you successfully retrieve a GUID for the process, these lines make the connection to
a FrameMaker session.
Lines 46–56
Now that the client has connected with a session, it can use the FDK to interact with that
session. These lines are standard FDK code to get the name of the active document for
the current session. You can add code to perform other actions such as adding menus to
the application window, manipulating the active document, or anything else you can do
via the FDK.
..............................................................................

IMPORTANT: Because they don’t have a Windows message processing loop, console
applications cannot handle notifications from the FDK, such as menu commands or
notifications such as FA_Note_PreSaveDoc.
..............................................................................

Compiling and registering the sample client
To compile the sample client in Microsoft Visual Studio 2010, follow these steps:
1. Create a project for a console application.
Use the Project Wizard to create a new project for a console application.
2. Set up the project options and settings as described in "Compiling, Registering, and
Running FDK Clients".
..............................................................................

IMPORTANT: Your link settings must include fdk.lib and api.lib. but neither
fmdbms32.lib nor fmdebug.lib. In previous versions of the FDK, fmdbms32.lib and
fmdebug.lib were required to compile. These libraries are now obsolete, but we include
them so you don’t have to change the link settings to compile existing FDK projects. If
a remote client fails to start up and you see these libraries mentioned in the error text,
then you must remove them from your link settings and recompile.
..............................................................................

Compile the client.

FDK Programmer’s Guide

53

5

G e t t i n g St a r t e d w i t h F D K 1 2

Writing an Asynchronous FDK Client

4. Register the client
There are three ways to register an asynchronous client. See "Registering asychronous
clients".
You must also be sure the end user has a correct installation to run asynchronous clients.
See "End user installations".
5. Connect the client with a named FrameMaker process.
To connect with a named FrameMaker process:
– On your machine, register the FrameMaker process as a server. See "Registering
multiple FrameMaker processes as servers". Be sure to register it with a name. See
"Registering a name for a FrameMaker process".
– In a command window, type the filename for the client, followed with the name of the
FrameMaker process the argument.
– To connect to the default FrameMaker process, use the process name,
FrameMaker.API.1.
For example, type remote.exe process_name, where process_name is the name
you assigned to a FrameMaker process. Note that unlss you registered the process to
start up automatically, that process must be running when you invoke the sample client.

Summary of supporting functionality
To support communication with a FrameMaker process, the FDK provides the
following functions:
Function

54

Purpose

F_ApiWinConnectSession()

Initiates communication between the calling
process and an identified FrameMaker process

F_ApiDisconnectFromSession()

Severs communication with a FrameMaker
process

F_ApiSetClientDir()

Identifies a directory the FrameMaker process
associates with an unregistered client

F_ApiShutDown()

Closes a client’s connection with the API

F_ApiWinInstallDefaultMessag
eFilter()

Registers the default FDK message filter for a
COM session.

F_ApiService()

useful if you are providing a replacement for
F_ApiRun().

F_ApiStartup()

See the description after the table

FDK Programmer’s Guide

Example: adding menus and commands

Function

...

G e t t i n g St a r t e d w i t h F D K 1 2

Purpose

F_ApiAlive()
F_ApiErr(message)

Prints client name and message to console.

F_ApiRun

provides the minimum functionality required in
an FDK client’s main() function

Using F_ApiStartup(F_FdFuncT) the F_FdFuncT argument is ignored because
Windows RPC is not based on sockets. F_ApiStartup queries the application’s ersion
information for client configuration data, if present, and connects to FrameMaker.
For information on these functions and properties, see the FDK Programmer’s
Reference.

Example: adding menus and commands
The following code adds a menu named “Database” to the Special menu. The menu has
two commands “Load Database” and “Query Database”.

FDK Programmer’s Guide

55

5

G e t t i n g St a r t e d w i t h F D K 1 2

Example: adding menus and commands

When the user selects either of the commands, a prompt is displayed.

#include "fapi.h"

#define LOAD 1
#define QUERY 2
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
F_ObjHandleT specialMenuId, databaseMenuId;
/* Get the ID of the special menu. */
specialMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"SpecialMenu");
/* Define the menu and add it to the Edit menu. */
databaseMenuId = F_ApiDefineAndAddMenu(specialMenuId,
"DatabaseMenu",
"Database");
/* Define the commands and add them to the Special menu. */
F_ApiDefineAndAddCommand(LOAD, databaseMenuId,
"LoadDatabase", "Load Database","\\!LD");
F_ApiDefineAndAddCommand(QUERY, databaseMenuId,
"QueryDatabase", "Query Database", "\\!QD");
}
VoidT F_ApiCommand(command)
IntT command;
{
switch(command)
{
case LOAD: /* Code to load database goes here. */
F_ApiAlert((ConStringT)"Load Command Executed!!\n" ,

56

FDK Programmer’s Guide

Next Steps

...

G e t t i n g St a r t e d w i t h F D K 1 2

FF_ALERT_CONTINUE_NOTE);
break;
case QUERY: /* Code to query database goes here. */
F_ApiAlert((ConStringT)"Query Command Executed!!\n" ,
FF_ALERT_CONTINUE_NOTE);
break;
}
}

Next Steps
By now, you would have become familiar with the basic operations of the FDK. Here
are the suggested next steps that will help you use the FDK more effectively:


Study the Programmer’s Guide to understand the detailed flow and usage model



Review the samples provided (available in the samples folder of the FDK
installation) and write your own program modeled on them.



Refer to the FDK Programmer’s Reference for details of syntax and examples

FDK Programmer’s Guide

57

5

58

G e t t i n g St a r t e d w i t h F D K 1 2

Next Steps

FDK Programmer’s Guide

PART II

..........................................

Frame Product Architecture

1

Frame Session Architecture

..................................
.....

1

This chapter discusses the general organization of FrameMaker product sessions from a
programmer’s perspective. It provides useful background information for programmers
who want to use the Frame API.

Identifying objects
The API assigns a unique ID to each object. Most API functions that manipulate objects
require you to specify this ID. An object’s ID is valid only as long as the object is
available in the current FrameMaker product session. For example, suppose you have a
document with a rectangle drawn in it. When you open the document, the API assigns
an ID to the FO_Rectangle object that represents the rectangle. As long as the
document is open, the ID of the FO_Rectangle object remains the same. However,
if you exit the document and then reopen it, the API may assign a new ID to the
rectangle.
In addition to IDs, there are two types of identifiers that are persistent between sessions:


Unique object names



Unique persistent identifiers (UIDs)

Each object generally has either an FP_Name property specifying a unique object
name or an FP_Unique property specifying a UID.

Unique object names
There are many types of objects that you can assign unique names to in the user
interface. These objects, which are called named objects, include:


FO_Book



FO_CharFmt



FO_Color



FO_CombinedFontDfn



FO_Command



FO_CondFmt
FDK Programmer’s Guide

61

1

Frame Session Architecture

Identifying objects



FO_ElementDef



FO_FmtChangeList



FO_MarkerType



FO_MasterPage



FO_Menu



FO_MenuItemSeparator



FO_PgfFmt



FO_RefPage



FO_RulingFmt



FO_TiFlow



FO_TiText



FO_TblFmt



FO_UnanchoredFrame (named frames on reference pages only)



FO_VarFmt



FO_XRefFmt

The API provides a function named F_ApiGetNamedObject(), which gets the ID of
a named object with a specified name.
..............................................................................

IMPORTANT: A document can contain several flows with the same name. For example,
a document can contain several A flows. To get the ID of a specific flow, first get the ID
of a text frame in that flow, for example, the text frame for the current text location, and
then query the text frame’s FP_Flow property.
..............................................................................

Unique persistent identifiers (UIDs)
The API and MIF identify unnamed objects with UIDs. An unnamed object is an object
that doesn’t have a unique name. For example, FO_Pgf objects are unnamed.
UIDs are unique within documents. An object’s UID remains the same as long as the
object is in the same document. The API provides a function named
F_ApiGetUniqueObject(), which gets an object’s ID from its UID.
..............................................................................

IMPORTANT: If you copy an object and then paste it, the FrameMaker product
considers the pasted object a new object and assigns a new UID to it. This is also true
true for a paragraph that is conditionalized. If the entire paragraph is of a given

62

FDK Programmer’s Guide

Representing object characteristics with properties

...

Frame Session Architecture

condition, and that condition is hidden and then shown, the paragraph will have a new
UID.
..............................................................................

Representing object characteristics with properties
Each object has a property list, or set of properties that represent its characteristics. Each
property has a value associated with it. For example, if a paragraph has two tabs, the
value of its FP_NumTabs property is 2. A property value can be more than an integer.
It can also be a string, a pointer to a structure that contains a set of strings, or a variety
of other things. The following table summarizes the different data types property values
can be.
Property data type

What the property value represents

IntT

An integer, enum, boolean, or ordinal value. For many
IntT properties, the API provides defined constants,
such as True and False.

F_IntsT

A set of integers or a set of IDs.

F_UIntsT

A set of unsigned integers.

MetricT

A measurement value.

F_MetricsT

A set of metrics.

StringT

A character string.

F_StringsT

A set of character strings.

F_ObjHandleT

The ID of another object.

F_PointsT

A set of x-y coordinate pairs.

F_TabsT

A set of tab descriptions.

F_TextLocT

A point (location) in text.

F_TextRangeT

A range or selection of text.

F_ElementCatalogEntriesT

The list of elements in the Element Catalog.

F_AttributeDefsT

An set of attribute definitions.

F_AttributesT

An set of attributes.

F_ElementRangeT

An element selection.

FDK Programmer’s Guide

63

1

Frame Session Architecture

Representing object characteristics with properties

The API uses MetricT data to express measurement values. This manual uses
constants to represent conventional measurement system units as MetricT data. For
example, the constant in represents an inch and the constant pts represents a point
in MetricT units, for example 5 inches (5* 4718592) are represented as 5*in.
For more information on the MetricT type and other data types and data structures
listed in the table above, see Chapter 4, “Data Types and Structures Reference,” of the
FDK Programmer’s Reference.
Many property values are pointers to data structures. For example, FO_Doc objects
have a property named FP_Dictionary that specifies words that the Spelling
Checker will permit in a document. FP_Dictionary is an FT_Strings property.
Its value is a pointer to an F_StringsT structure, which is defined as:
typedef struct {
UIntT len;
/* Number of permitted words */
StringT *val; /* Vector of permitted words */
} F_StringsT;

Property lists
At the highest level, the API represents each object’s property list with a
F_PropValsT structure. The F_PropValsT structure is defined as:
typedef struct {
UIntT len; /* Number of properties in list */
F_PropValT *val; /* Property-value pairs */
} F_PropValsT;

The F_PropValT structure, which provides an individual property-value pair, is
defined as:
typedef struct {
F_PropIdentT propIdent; /* The property identifier */
F_TypedValT propVal; /* The property value */
} F_PropValT;

The F_PropIdentT structure, which identifies a property by either its property
number constant (one of the constants beginning with FP_) or a property name, is
defined as:
typedef struct {
IntT num; /* The property number constant */
StringT name; /* The property name */
} F_PropIdentT;

Most properties are identified by property number constants. Only inset facets, a special
type of properties, are identified by names. For information on insets, see Chapter 12,

64

FDK Programmer’s Guide

Representing object characteristics with properties

...

Frame Session Architecture

“Using Imported Files and Insets.” If a property is identified by a name,
F_PropIdentT.num is 0.
The F_TypedValT structure is defined as:
typedef struct {
IntT valType; /* The type of value. See table below */
union {
StringT sval; /* String value */
F_StringsT ssval; /* Set of strings */
F_MetricsT msval; /* Set of metrics */
F_PointsT psval; /* Set of points */
F_TabsT tsval; /* Set of tabs */
F_TextLocT tlval; /* Text location */
F_TextRangeT trval; /* Text range */
F_ElementCatalogEntriesT csval; /* Element Catalog */
F_AttributeDefsT adsval; /* Attribute definitions */
F_AttributesT asval; /* Attribute values */
F_ElementRangeT *erng; /* Element range */
F_IntsT isval; /* Set of integers */
F_UIntsT uisval; /* Set of unsigned integers */
IntT ival; /* Integer */
} u;
} F_TypedValT;

The constants used in the valType field are described in the following table.
valType constant

Property data type

u field

FT_Integer

IntT

ival

FT_Ints

F_IntsT

isval

FT_Metric

MetricT

ival

FT_Metrics

F_MetricsT

msval

FT_String

StringT

sval

FT_Strings

F_StringsT

ssval

FT_Id

F_ObjHandleT

ival

FT_Points

F_PointsT

psval

FT_Tabs

F_TabsT

tsval

FT_TextLoc

F_TextLocT

tlval

FT_TextRange

F_TextRangeT

trval

FDK Programmer’s Guide

65

1

Frame Session Architecture

Representing object characteristics with properties

valType constant

Property data type

u field

FT_UInts

F_UIntsT

uisval

FT_UBytes

F_UBytesT

No field

FT_ElementCatalog

F_ElementCatalogEntriesT

csval

FT_AttributeDefs

F_AttributeDefsT

adsval

FT_Attributes

F_AttributesT

asval

FT_ElementRange

F_ElementRangeT

erng

..............................................................................

IMPORTANT: Integer (IntT), metric (MetricT), and ID (F_ObjHandleT) values are
all put in the ival field of the u union.
..............................................................................

Example
Suppose the user creates a paragraph format named Heading, which has a 1-inch left
indent and has Keep With Next Paragraph turned on. The API represents this paragraph
format with an FO_PgfFmt object. The following are some of the object’s properties
and their values.

66

Property

Data type

Value

FP_Name

StringT

Heading

FP_KeepWithNext

IntT

True

FP_LeftIndent

MetricT

1*in

FDK Programmer’s Guide

FrameMaker product sessions

...

Frame Session Architecture

The property list for the FO_PgfFmt object and the properties in the previous table are
represented graphically in Figure 1-1. FO_PgfFmt objects have many other properties
that are not shown in the illustration.
F_PropValsT
len: 3
val:

val[0]

val[1]

val[2]

propIdent

propIdent

propIdent

num: FP_Name
name: NULL

num: FP_KeepWithNext
name: NULL

num: FP_LeftIndent
name: NULL

propVal

propVal

propVal

valType: FT_String

valType: FT_Integer

valType: FT_Metric

u

u

u

sval: Heading

ival: True

ival: 1*in

Figure 1-1 Some FO_PgfFmt properties

FrameMaker product sessions
The fundamental entity in Frame architecture is a session. Each instance of a
FrameMaker product that the user starts is a session. FrameMaker allows the user to
have many open documents and books in a session.
Of the open documents and books in a session, only one document or book is active at
a time. An open document or book is active if it has the input focus.

FDK Programmer’s Guide

67

1

Frame Session Architecture

FrameMaker product sessions

How the API represents sessions
The API represents each FrameMaker product session with an FO_Session object,
whose properties provide the following categories of information about the session:


System information, such as the operating system, the current FrameMaker product
version, and the current directory



The automatic save settings



Names of fonts available on the system



IDs of the objects that represent open and active documents and books



Whether the FrameMaker product reformats and redisplays documents after changes
have been made



Whether element reformatting and validation is turned on (for FrameMaker
structured documents)

Suppose you start FrameMaker on a Window System platform and open a document
named mydoc. The API represents this session with an FO_Session object. The
following are some of its properties.
Property

Type

Value

FP_ProductName

FT_String

FrameMaker

FP_VersionMajor

FT_Integer

5

FP_WindowSystem

FT_String

Windows

FP_AutoSaveSeconds

FT_Integer

300

FP_ActiveDoc

FT_Id

ID of the object that represents mydoc

How the API indicates which documents and books are open
The API represents a document with an FO_Doc object. The API maintains a linked
list of the FO_Doc objects that represent a session’s open documents. The
FO_Session property, FP_FirstOpenDoc, specifies
the ID of the first FO_Doc object in the list. The FO_Doc property,
FP_NextOpenDocInSession, specifies the ID of the next FO_Doc object in the list.
The list of FO_Doc objects that represent open documents is not in any particular
order. The FO_Doc object specified by FP_FirstOpenDoc does not necessarily
represent the first document the user opened.

68

FDK Programmer’s Guide

FrameMaker product sessions

...

Frame Session Architecture

The API represents a book with an FO_Book object. The API also
maintains the FO_Book objects that represent the session’s open books
in a linked list. The FO_Session property, FP_FirstOpenBook, specifies the ID
of the first FO_Book object in the list. The FO_Book property,
FP_NextOpenBookInSession, specifies the next FO_Book object in the list. As
with the list of FO_Doc objects, the linked list of FO_Book objects is not in any
particular order.
How the API indicates which document or book is active
FO_Session has two properties, FP_ActiveDoc and FP_ActiveBook, that
specify the IDs of the objects that represent the active document and the active book.
Only one document or one book can be active at a time. If there is no active document
or book, these properties are set to 0. Invisible documents and books can’t be active.
Example
Suppose you start FrameMaker and open the books and documents shown in Figure 1-2.
The Frame API represents the session with the objects shown in Figure 1-3.

Figure 1-2 A FrameMaker\session with open documents and books

FDK Programmer’s Guide

69

1

Frame Session Architecture

FrameMaker product sessions

FP_FirstOpenBook

FO_Book
(Manual.book)

FP_NextOpenBookInSession
FO_Book
(Manual2.book)

FO_Session
FP_FirstOpenDoc

FO_Doc
(2Chapter)

FP_NextOpenDocInSession
FO_Doc
FP_ActiveDoc

(1Chapter)

Figure 1-3 API representation of a session with open documents and books

Although Manual.book is iconified, the API still considers it open. Although
FP_FirstOpenDoc specifies 2Chapter, it is not necessarily the first document that
was opened.
How the API indicates which fonts are available in a session
The following FO_Session properties specify which fonts are available in the current
session:

70



FP_FontFamilyNames specifies the available families, for example, Helvetica
and Times.



FP_FontVariationNames specifies the available variations, for example,
Narrow and Oblique.



FP_FontWeightNames specifies the available weights, for example, Bold and
Regular.



FP_FontAngleNames specifies the available angles, for example, Italic and
Regular.

FDK Programmer’s Guide

FrameMaker product sessions

...

Frame Session Architecture

The FP_FontFamilyNames, FP_FontVariationNames,
FP_FontWeightNames, and FP_FontAngleNames properties determine which
choices appear in the Family, Weight, Angle, and Variation fields of the Character
Designer and Paragraph Designer, and the pull-right menu items in the Format menu.
Each of the properties specifies an F_StringsT structure, which is defined as:
typedef struct {
UIntT len;
/* Number of strings */
StringT *val; /* Font names */
} F_StringsT;

For example, if Courier, Helvetica, and Times are the only font families available in the
current session, the fields of the F_StringsT structure specified by
FP_FontFamilyNames have the following values:
len: 4
val: {"","Courier","Helvetica","Times"}

Properties that specify font families, angles, weights, and variations use the index of the
val array. For example, the FO_CharFmt property, FP_FontFamily, specifies the
font family for a character format. Given the F_StringsT values shown above, if the
font family for a character format is Helvetica, the value of the format’s
FP_FontFamily property is 2.
Although a specific angle, weight, or variation may be in one of the lists described
above, it may not be available for all combinations of font families, angles, weights, and
variations. For example, the Bold weight may be available for Times and Helvetica, but
not for Zapf Chancery. The FDK provides a convenience function named
F_ApiFamilyFonts(), which returns all the permutations of font families, angles,
weights, and variations in a FrameMaker product session. For more information, see
“F_ApiFamilyFonts()” on page 158 of the FDK Programmer’s Reference.

FDK Programmer’s Guide

71

2

Frame Document Architecture

..................................
.....

2

This chapter describes Frame documents and their components and shows how the
Frame API represents them.

Documents
A document is a set of pages with graphic objects and text that the user creates with a
FrameMaker product and stores in a file.

What the user sees
When you create a new document, you can use a template to create it, or you can create
a custom document. Any document can be a template. Because the FrameMaker
product copies everything from a template to a new document, most users prefer to use
templates containing only layout and formatting information. FrameMaker provides
ready-made templates for a variety of document types.
You can’t create a document completely from scratch—the document must have a
certain set of default objects for the FrameMaker product to work correctly. To ensure
that all documents have this set of objects, the FrameMaker product always uses a
template to create a new document. Even if you choose the Custom document option,
the FrameMaker product creates the new document from a default template. This
custom document template is specified in the maker.ini file.

FDK Programmer’s Guide

73

2

Frame Document Architecture

Documents

When the user attempts to create a new document from an ASCII text file or a MIF file
that doesn’t provide the necessary objects, FrameMaker uses the ASCII template
specified in the maker.ini file.
When you instruct FrameMaker to save a document, it lists the document’s objects and
their properties in a file. By default, FrameMaker writes the information to a Frame
binary format file. You can also choose to save a document as a MIF file.

How the API represents documents
A document actually consists of much more than text and graphic objects. It includes
information specifying a variety of other things, such as formatting, user preferences,
and the FrameMaker product’s default behavior. The API represents the information in
a document with a set of objects. The following table summarizes the information a
document can contain and the objects the API uses to represent it.

74

Types of objects that
represent it

Type of information

Function

Global document
information

Specifies the document’s general
characteristics, some aspects of the
FrameMaker product’s behavior when
the document has input focus, and IDs
of other objects that constitute the
document

FO_Doc

Pages

Organize text and graphic objects in
the document

FO_BodyPage
FO_MasterPage
FO_RefPage
FO_HiddenPage

Graphic objects

Describe graphic objects in the
document

FO_UnanchoredFrame
FO_AFrame
FO_Group
FO_Arc
FO_Rectangle
FO_Ellipse
FO_RoundRect
FO_Polyline
FO_Polygon
FO_Line
FO_TextLine
FO_TextFrame
FO_Inset
FO_Math

Text columns

Contain text

FO_SubCol

Text frames

Contain text

FO_TextFrame

FDK Programmer’s Guide

Documents

...

Frame Document Architecture

Types of objects that
represent it

Type of information

Function

Text flows

Specify how text frames in the
document are linked

FO_Flow

Paragraph Catalog
formats

Specify tags that the user can apply to
a paragraph to change its formatting

FO_PgfFmt

Paragraphs

Contain the document’s text and
provide formatting information for
individual paragraphs

FO_Pgf

Character Catalog
formats

Specify tags that the user can apply to
a selection of characters to change its
formatting

FO_CharFmt

Condition formats

Specify tags that the user can apply to
text to indicate that it belongs to a
particular variation of the document

FO_CondFmt

Markers

Describe placeholders that contain
hidden text

FO_Marker

Marker types

Specifies a named catagory of markers

FO_MarkerType

Cross-reference
formats

Specify the wording and typographic
style of cross-references

FO_XRefFmt

Cross-reference
instances

Describe instances of cross-references
in the document

FO_XRef

Variable formats

Specify units of text and systemsupplied information that the user can
use multiple times in a document

FO_VarFmt

Variable instances

Describe instances of variables in the
document

FO_Var

Footnotes

Describe footnotes

FO_Fn

Table ruling formats

Specify rulings and shadings that the
user can apply to individual table cells

FO_RulingFmt

Table Catalog
formats

Specify table formats that the user can
apply to a table and that provide
default numbers of columns and rows
for new tables

FO_TblFmt

Tables

Describe instances of tables in the
document and specify formatting
information, such as alignment,
ruling, and shading

FO_Tbl
FO_Row
FO_Cell

Colors

Specify colors that the user can apply
to graphic objects and text

FO_Color

FDK Programmer’s Guide

75

2

Frame Document Architecture

Documents

Types of objects that
represent it

Type of information

Function

Text insets

Describe text that is imported by
reference

FO_TiApiClient
FO_TiFlow
FO_TiText
FO_TiTextTable

Structural element
definitions

Specify tags that specify the
organization of parts of a structured
document

FO_ElementDef

Structural element
instances

Describe instances of structural
elements in a structured document

FO_Element

Format rules

Specify sets of format rule clauses

FO_FmtRule

Format rule clauses

Specify which formats to apply to
elements in various contexts

FO_FmtRuleClause

Format change list

Specify format changes applied to an
element in a specific context

FO_FmtChangeList

Rubi composites

Describe the oyamoji (base word) and
rubi (phonetic spelling) of certain
words in Asian text

FO_Rubi

Combined font
definitions

Describe pairs of Asian and Western
fonts that are treated as a single font
family

FO_CombinedFontDfn

The other sections of this chapter discuss the different types of information in a
document.

76

FDK Programmer’s Guide

Documents

...

Frame Document Architecture

How the API organizes the objects that constitute a document
The API uses an FO_Doc object to organize the objects that constitute
a document. FO_Doc objects have a number of properties that specify
the IDs of other objects in the document. Many of these properties
specify the ID of the first object in a linked list of objects. For example,
FP_FirstPgfFmtInDoc specifies the first FO_PgfFmt object (Paragraph Catalog
format) in the list of FO_PgfFmt objects in the document. Each FO_PgfFmt object
has a FP_NextPgfFmtInDoc property that specifies the next FO_PgfFmt object in
the list. If you want to get all the FO_PgfFmt objects in a document, you get the
FO_PgfFmt object specified by FP_FirstPgfFmtInDoc and traverse the links to
the other objects.
Document object property

Object that the property specifies

FP_FirstGraphicInDoc

The first graphic object (for example,
FO_UnanchoredFrame or FO_Line) in the
list of graphic objects

FP_FirstColorInDoc

The first FO_Color in the list of FO_Color
objects

FP_FirstPgfInDoc

The first FO_Pgf in the list of FO_Pgf objects

FP_FirstMarkerInDoc

The first FO_Marker in the list of
FO_Marker objects

FP_FirstMarkerTypeInDoc

The first FO_MarkerType, in the list of marker
types

FP_FirstVarInDoc

The first FO_Var in the list of FO_Var objects

FP_FirstVarFmtInDoc

The first FO_VarFmt in the list of
FO_VarFmt objects

FP_FirstXRefInDoc

The first FO_XRef in the list of FO_XRef
objects

FP_FirstXRefFmtInDoc

The first FO_XRefFmt in the list of
FO_XRefFmt objects

FP_FirstFnInDoc

The first FO_Fn in the list of FO_Fn objects

FP_FirstTblInDoc

The first FO_Tbl in the list of FO_Tbl objects

FP_FirstFlowInDoc

The first FO_Flow in the list of FO_Flow
objects

FP_FirstPgfFmtInDoc

The first FO_PgfFmt in the list of
FO_PgfFmt objects

FP_FirstCharFmtInDoc

The first FO_CharFmt in the list of
FO_CharFmt objects

FDK Programmer’s Guide

77

2

Frame Document Architecture

Documents

Document object property

Object that the property specifies

FP_FirstCondFmtInDoc

The first FO_CondFmt in the list of
FO_CondFmt objects

FP_FirstTblFmtInDoc

The first FO_TblFmt in the list of
FO_TblFmt objects

FP_FirstRulingFmtInDoc

The first FO_RulingFmt in the list of
FO_RulingFmt objects

FP_FirstSelectedGraphicInDoc

The first graphic object in the list of selected
graphic objects

FP_MainFlowInDoc

FO_Flow that represents the main flow

FP_FirstElementDefInDoc

First structural element definition in the list of
element definitions in a FrameMaker document

FP_FirstFmtChangeListInDoc

First format change list in the list of format change
lists in a document

FP_FirstBodyPageInDoc or
FP_LastBodyPageInDoc

The first or last FO_BodyPage in the list of
FO_BodyPage objects

FP_FirstMasterPageInDoc or

FP_LastMasterPageInDoc

The first or last FO_MasterPage in the list of
FO_MasterPage objects

FP_FirstRefPageInDoc or
FP_LastRefPageInDoc

The first or last FO_RefPage in the list of
FO_RefPage objects

FP_HiddenPage

The hidden page (FO_HiddenPage)

FP_SelectedTbl

The selected table object

FP_FirstTiInDoc

The first FO_TiApiClient, FO_TiFlow,
FO_TiText, or FO_TiTextTable in the list
of text insets

FP_FirstRubiInDoc

The first FO_Rubi in the list of rubi composites

FP_FirstCombinedFontDfnInDoc

The first FO_CombinedFontDfn in the list of
combined font definitions

FP_FirstBodyPageInDoc, FP_FirstMasterPageInDoc, and
FP_FirstRefPageInDoc point to the lists of pages in a document. These lists are
ordered to reflect the order of the pages. All other lists (including the list of FO_Pgf
objects) are not ordered. The terms first and last indicate only the position of the objects
in an arbitrarily ordered list. There is no guarantee that a more recently added object will
come later in a list, nor is there a guarantee that the order of a list will remain the same
as the document is modified.

78

FDK Programmer’s Guide

Global document information

...

Frame Document Architecture

Global document information
FrameMaker products allow you to set global document information, characteristics
that apply generally to an entire document.

What the user sees
Global document information includes the following formatting characteristics:


Document page properties, which specify the document’s page numbering and
pagination style



Document condition properties, which specify whether conditional text appears and
whether formatting associated with condition tags overrides other formatting



Document and table footnote properties, which specify the appearance of the
footnotes, such as the footnote numbering and the default paragraph format



Change bar properties, which specify the appearance and position of change bars in
the document



The current text selection or insertion point

There is also global document information that affects how the FrameMaker product
behaves when the document is active. This type of global information includes:


The document dictionary, which lists words that you want the FrameMaker product
Spelling Checker to ignore



Type-in properties, which specify whether Smart Spaces or Smart Quotes is enabled



Equation properties, which specify default symbol sizes and fonts the FrameMaker
product uses when you add equations to the document



Printing properties, which specify the defaults that appear in the Print dialog box,
such as the printer name and the range of pages to print



View properties, which specify how FrameMaker displays and scrolls the document
in the window



Structure properties, which specify whether element boundaries appear and how the
Element Catalog appears for a structured document in a session.

FrameMaker saves most of the global document information with each document. For
example, if you set the zoom for a document to 140 percent and save and exit a
document, the next time you open the document, the zoom will be set to 140 percent.

FDK Programmer’s Guide

79

2

Frame Document Architecture

Global document information

How the API represents global document information
The Frame API represents global document information with FO_Doc object
properties.
How the API represents the selection in a document
The API uses several properties to specify what is selected in a document:


FP_TextSelection specifies a structure that provides the location of the insertion
point or the beginning and end of a text selection.



FP_FirstSelectedGraphicInDoc specifies the ID of the first graphic in the list
of selected graphics in a document.



FP_SelectedTbl specifies the ID of a table that contains the insertion point or
some selected cells.



FP_ElementSelection specifies the range of elements selected if the document
is a structured document in a session.

The following table summarizes the different types of selection in an unstructured
document and how these properties are set to represent them.
Selection state

How selection properties are set

No object is selected.
There is no text selection
or insertion point.

FP_TextSelection specifies an F_TextRangeT
structure for which the objId and offset fields of
F_TextRangeT.beg and F_TextRangeT.end are set to
0.
FP_FirstSelectedGraphicInDoc is 0.
FP_SelectedTbl is 0.

One or more graphic
objects are selected.

FP_TextSelection specifies an F_TextRangeT
structure for which the objId and offset fields of
F_TextRangeT.beg and F_TextRangeT.end are set to
0.
FP_FirstSelectedGraphicInDoc specifies the ID of
the first selected graphic in the document’s list of selected
graphics.

FP_SelectedTbl is 0.
There is an insertion point
or text selection (that isn’t
in a table cell, but may
include table anchors).

80

FDK Programmer’s Guide

FP_TextSelection specifies the location of the text
selection or insertion point

FP_FirstSelectedGraphicInDoc is 0.
FP_SelectedTbl is 0.

Global document information

Selection state

How selection properties are set

There is an insertion point
or text selection within a
single table cell.a

FP_TextSelection specifies the location of the text

...

Frame Document Architecture

selection or insertion point within the cell; for example, the ID of
the paragraph containing the insertion point, and the offset within
that paragraph.

FP_FirstSelectedGraphicInDoc is 0.
FP_SelectedTbl specifies the ID of the table containing the
cell.
If the current selection is in a paragraph, the paragraph´s
FP_InTextObj property specifies the ID of the cell that
contains the selection. The cell’s FP_CellColNum property
specifies the column number, and the cell’s FP_CellRow
property specifies the ID of its row.
An entire cell or set of
cells is selected.

FP_TextSelection specifies an F_TextRangeT
structure for which the objId and offset fields of
F_TextRangeT.beg and F_TextRangeT.end are set to
0.
FP_FirstSelectedGraphicInDoc is 0.
FP_SelectedTbl specifies the ID of the table containing the
cell. The table properties FP_TopRowSelection and
FP_BottomRowSelection specify the IDs of the first and
last rows containing selected cells. The FP_LeftColNum and
FP_RightColNum properties of the table specify the index
numbers of the outermost columns in the selection.

a. If an entire cell is selected, there is no text selection.

How the API represents the element selection in a structured FrameMaker document
In a structured FrameMaker document, the selection properties described in the
previous section behave as they would in an unstructured document. However,
structured FrameMaker documents have an additional selection property,
FP_ElementSelection, which specifies the selection in terms of the selected
element range or F_ElementRangeT structure.
The F_ElementRangeT structure is defined as:
typedef struct {
F_ElementLocT beg; /* Beginning of the element range. */
F_ElementLocT end; /* End of the element range. */
} F_ElementRangeT;

FDK Programmer’s Guide

81

2

Frame Document Architecture

Global document information

The F_ElementLocT structure specifies a location within an element. It is defined as:
typedef struct {
F_ObjHandleT parentId; /* Parent element ID. */
F_ObjHandleT childId; /* Child element ID. */
IntT offset; /* Offset within child/parent element. */
} F_ElementLocT;

The following table summarizes the different types of selection in a structured
FrameMaker document and how the fields of the F_ElementRangeT structure
specified by the FP_ElementSelection property are set to represent them.
Selection state

What the fields of the F_ElementRangeT structure specify

No object is selected.
There is no text selection
or insertion point.

beg.parentId: 0
beg.childId: 0
beg.offset: 0
end.parentId: 0
end.childId: 0
end.offset: 0

One or more graphic
objects are selected.

There is an insertion point
or text selection within an
element that has no
subelements.

beg.parentId: ID of the element containing the insertion
point or selection

beg.childId: ID of the child element immediately following
the insertion point or the beginning of the text selection

beg.offset: offset of the beginning of the selection or
insertion point from the beginning of the element containing it

end.parentId: ID of the element containing the insertion
point or selection

end.childId: ID of the child element immediately following
the insertion point or the end of the text selection

end.offset: offset of the end of the selection or insertion point
from the beginning of the element containing it

82

FDK Programmer’s Guide

Global document information

Selection state

An entire element or
range of elements
(excluding the highest
level element) is selected.

...

Frame Document Architecture

What the fields of the F_ElementRangeT structure specify

beg.parentId: ID of the element containing the first selected
element

beg.childId: ID of the first selected element
beg.offset: 0
end.parentId: ID of the element containing the first selected
element

end.childId: ID of the sibling element following the last
selected element, or 0 if there is no sibling element following the
last selected element

end.offset: 0
The highest level element
is selected.

beg.parentId: 0
beg.childId: ID of the highest-level element
beg.offset: 0
end.parentId:: 0
end.childId: 0
end.offset: 0

Example
Suppose you create the document shown in Figure 2-1.

Figure 2-1 A document

FDK Programmer’s Guide

83

2

Frame Document Architecture

Global document information

The API represents the document with an FO_Doc object. The following table lists
some of its properties.

84

Property

Type

Value

FP_Name

StringT

C:\Sales\Training\1Chapter

FP_ViewBorders

IntT

True

FP_ViewRulers

IntT

True

FP_ViewPageScrolling

IntT

FV_SCROLL_VERTICAL

FP_Zoom

MetricT

1 << 16

FP_IsIconified

IntT

False

FP_ViewTextSymbols

IntT

True

FP_IsOnScreen

IntT

True

FDK Programmer’s Guide

Pages

...

Frame Document Architecture

Pages
Frame documents have three kinds of visible pages: body pages, master pages, and
reference pages.

What the user sees
With FrameMaker, the user can change any of the visible pages.
Body pages
Body pages are what a user normally thinks of as the document’s pages. They organize
the text and graphic objects that appear in the body of a document.
Master pages
Master pages control the layout of body pages. Each body page is associated with one
master page, and each master page can be associated with zero or more body pages. A
master page provides the following for the body page:


The text frame layout, which defines the number, size, and placement of the page’s
text frames and the column layout within each text frame



The page background, which includes graphic objects and text frames (such as
headers and footers) with unnamed flows

By default, single-sided documents have at least one master page, which is named
Right. Double-sided documents have two master pages, named Right and Left.
FrameMaker products allow you to add your own custom master pages to both singlesided and double-sided documents.
When a FrameMaker product adds a body page, it uses a left or right master page object
as a background. It also copies all the text frames with named flows from that master
page to the body page. Once the FrameMaker product copies these text frames to the
body page, they are independent of the text frames on the master page from which they
were copied. If you change the text frames, it does not affect the master page.
A body page’s background appears when you view a body page on the
screen or print it. However, the background is part of the master page
and not the body page. The FrameMaker product superimposes the body page
on the background for displaying and printing. If you go to the master
page and change the graphic objects that constitute the background, the changes appear
when you view or print the body pages associated with the master page.

FDK Programmer’s Guide

85

2

Frame Document Architecture

Pages

Reference pages
Reference pages can contain named graphic frames. Named graphic frames provide
decoration, such as a thick line ruling, for paragraphs in the body pages. The Paragraph
Designer provides two settings, Frame Above and Frame Below, that allow you to
specify the named graphic frames you want to appear above or below a paragraph.
Reference pages can also contain special flows that control the appearance of generated
documents. For example, a Table of Contents document normally has a flow named
TOC on one of its reference pages.

How the API represents pages
FrameMaker represents body pages, master pages, and reference pages with
FO_BodyPage, FO_MasterPage, and FO_RefPage objects, respectively.
In addition to these pages, a document can also have a hidden page, which stores hidden
conditional text. The user cannot see or directly modify hidden pages. FrameMaker
represents each hidden page with an FO_HiddenPage object.
Page objects have a number of common properties. These properties specify the
following characteristics of a page:


The dimensions of the page



Its type (body, master, reference, or hidden)



Its numbering



IDs of the objects that represent its page frame and its sibling pages

A page object does not actually contain the text and graphic objects
that appear on a page. Instead, it has a property named FP_PageFrame, which
specifies the ID of a page frame. A page frame is an invisible unanchored frame whose
dimensions match those of the page. (For more information on unanchored frames, see
“Graphic objects” on page 90.) The API represents a page frame with an
FO_UnanchoredFrame object. This FO_UnanchoredFrame object has properties
that specify the IDs of the first and last objects in the linked list of API graphic objects
that appear directly on the page.

86

FDK Programmer’s Guide

Pages

...

Frame Document Architecture

Suppose you create a body page with a single text frame as shown in Figure 2-2.

Figure 2-2 Single text frame on a body page

The API represents the body page in Figure 2-2 with the objects shown in Figure 2-3.
The FO_BodyPage object does not have a property that specifies the ID of the
FO_TextFrame object. Instead, it has a property, named FP_PageFrame, that
specifies the ID of its page frame (an FO_UnanchoredFrame object). The page
frame properties, FP_FirstGraphicInFrame and FP_LastGraphicInFrame,
both specify the ID of the FO_TextFrame object, since it is the only object that
appears directly on the page.
FO_BodyPage

FP_PageFrame

FO_UnanchoredFrame
(page frame)

FP_FirstGraphicInFrame
FO_TextFrame
FP_LastGraphicInFrame

Figure 2-3 Objects for a body page with a single text frame

A FrameMaker product automatically creates and destroys the page frame when it
creates and destroys the page. The page frame is not accessible to the user. However, as
a developer, you need to use it to get the objects on a page.

FDK Programmer’s Guide

87

2

Frame Document Architecture

Pages

How the API organizes pages
The API maintains the different types of visible pages in a document (body pages,
master pages, and reference pages) in separate linked lists. FO_Doc objects have the
following properties that specify the first and last page object in each list:


FP_FirstBodyPageInDoc and FP_LastBodyPageInDoc



FP_FirstMasterPageInDoc and FP_LastMasterPageInDoc



FP_FirstRefPageInDoc and FP_LastRefPageInDoc

Each page object has two properties, FP_PagePrev and FP_PageNext, that specify
the IDs of the page objects before and after it in the list. When you delete a page, the API
removes the object that represents it and updates the FP_PagePrev and
FP_PageNext properties for all the FO_Page objects before and after it.
FO_Doc objects also have a property named FP_CurrentPage that specifies the ID
of the current page. The current page is the page that appears on the screen. If more than
one page appears on the screen, it is the page that appears with a dark border around it.
Suppose you create a double-sided document that has three body pages, two master
pages (Left and Right), and a single reference page, as shown in Figure 2-4. The current
page is the Right master page.

1

Body Pages

Right

Master Pages

1

Reference Page

Figure 2-4 Document with body, master, and reference pages

88

FDK Programmer’s Guide

Pages

...

Frame Document Architecture

FrameMaker products organize the objects as shown in Figure 2-5.
FP_FirstBodyPageInDoc

FO_BodyPage

FP_PagePrev

FP_PageNext

(Body page 1)

FO_BodyPage

FP_PagePrev

FP_PageNext

(Body page 2)

FO_BodyPage

FP_LastBodyPageInDoc

(Body page 3)

FO_Doc

FP_FirstRefPageInDoc

FO_RefPage
(Reference page)

FP_LastRefPageInDoc

FP_CurrentPage

FO_MasterPage

FP_PagePrev

(Right master page)

FP_PageNext

FP_FirstMasterPageInDoc

FO_MasterPage
FP_LastMasterPageInDoc

(Left master page)

Figure 2-5 Example document and page objects

FDK Programmer’s Guide

89

2

Frame Document Architecture

Graphic objects

How the API represents hidden pages
If the user chooses to hide conditional text in the document, the FrameMaker product
adds a hidden page to the document to store the hidden text. A document can have only
one hidden page. FrameMaker products represent the hidden page with an
FO_HiddenPage object. The FO_Doc property FP_HiddenPage specifies its ID.
The hidden page has only one text flow, named HIDDEN. For more information on how
the API represents hidden conditional text, see page 120.
How the API represents master pages
Both single-sided and double-sided documents have default master pages, named Right
and Left. In single-sided documents, the Left master page is not visible to the user.
However, you can get and set its properties with the API.

Graphic objects
A graphic object is anything the user can draw with the Tools palette, or an imported
graphic.

What the user sees
A graphic object can be:

90



An anchored frame, which is a container for graphic objects that is tied to a specific
location in text.



An unanchored frame, which is a container for graphic objects that is not tied to a
specific location in text.



A simple geometric shape, which is a line, an arc, a rectangle, a rounded rectangle,
an ellipse, a polyline, or a polygon.



A group, which is an invisible graphic object that holds together a set of other
graphic objects.



A text line, which is a single line of text that isn’t in a paragraph or flow (for more
information on text lines, see “Text” on page 112).



A text frame, which is a container for text in a flow (for more information on text
frames, see “Text” on page 112).



An imported graphic such as a bitmap or a PostScript file created with another
application.



An inset or imported graphic.



A math equation, which describes a formatted equation.

FDK Programmer’s Guide

Graphic objects

...

Frame Document Architecture

You can draw a graphic object directly on a page in a document. A graphic object drawn
directly on a page doesn’t move as you edit the text around it. You can also draw a
graphic object inside an anchored or unanchored frame. When you move a frame, all the
graphic objects inside it move with it. You can nest frames; that is, you can draw a frame
within a frame within a frame.
Draw order
The graphic objects in a frame have a back-to-front order or draw order that specifies
the order in which the FrameMaker product draws them. By default, the draw order is
the same as the order in which you created the objects. When graphic objects overlap,
the ones in front (at the end of the draw order) obscure those in back. You can change
the draw order by selecting a graphic object and choosing Front or Back from the Tools
palette.
Groups
You can create a group from one or more graphic objects. This allows you to manipulate
them as a single object. When you resize the group, the FrameMaker product
automatically resizes the group’s component objects proportionally.
Anchored frames
You can draw graphic objects in anchored frames, which are tied to text symbols named
anchor symbols (). An anchor symbol (and its anchored frame) moves with the text to
which it is attached. You can specify a variety of parameters that determine where a
frame appears in relation to its anchor symbol. For example, it can be below the line
containing the anchor symbol or at the bottom of the text frame containing the anchor
symbol. Unlike other graphic objects, the anchored frame cannot be drawn directly on a
page or into another frame; it can only be created in text.

How the API represents graphic objects
The API represents each type of graphic object with a different type of API object. For
example, it represents polygons with FO_Polygon objects and text frames with
FO_TextFrame objects.
All types of API graphic objects1 have properties that provide the following
information:


The graphic object’s format—that is, characteristics such as its fill pattern and border
width



The graphic object’s location and angle

.................................
1. This manual uses the term API graphic object to refer to objects (such as FO_Polygon and
FO_TextFrame objects) that the API uses to represent the graphic objects (such as polygons and text
frames) that appear on a page.

FDK Programmer’s Guide

91

2

Frame Document Architecture

Graphic objects



IDs of the graphic object’s parent, sibling, and child objects

Some format properties do not affect some graphic objects. For example, an
FO_Rectangle object, like all other objects, has an FP_ArrowType property. This
property can have a value, but that value will not affect the appearance of the rectangle
that the object represents.
All types of API graphic objects also have several properties that are specific to them.
For example, FO_Arc objects have a property named FP_Theta that specifies an
arc’s theta value.
Suppose you create the arrow shown in Figure 2-6.

Figure 2-6 Arrow in an unanchored frame

The API represents the arrow with an FO_Line object, whose properties include those
shown in the following table.
Property

Type

Value

FP_FrameParent

F_ObjHandleT

ID of the frame containing the arrow

FP_Pen

IntT

FV_FILL_BLACK

FP_LocX

MetricT

.25*in

FP_LocY

MetricT

1.125*in

FP_HeadArrow

IntT

True

FP_ArrowType

IntT

FV_ARROW_HOLLOW

How the API organizes graphic objects
The API maintains each API graphic object in at least two linked lists:


The list of all the API graphic objects in the document
For convenience, the API maintains a linked list of all the API graphic objects in a
document. The FO_Doc property FP_FirstGraphicInDoc specifies the ID of
the first object in the list. API graphic objects have a property named
FP_NextGraphicInDoc, which specifies the ID of the next API graphic object in

92

FDK Programmer’s Guide

Graphic objects

...

Frame Document Architecture

the list. If you traverse this list, you will cover every graphic object in a document.
The order of the list is completely random.


The list of API graphic objects in the graphic object’s parent frame
Each API graphic object (except an anchored frame and a page frame)
has exactly one parent frame object. The parent frame is the frame that contains the
graphic object. The API maintains a linked list of the child objects in each frame.
FO_UnanchoredFrame and FO_AFrame objects have
FP_FirstGraphicInFrame and FP_LastGraphicInFrame properties,
which specify the first and last objects in the list of their child objects. All API
graphic objects have FP_PrevGraphicInFrame and
FP_NextGraphicInFrame properties, which specify the objects before and after
them in the list. The order of the objects in the linked list is the same as the draw
order of the graphic objects in a frame.

Like the frames they represent, API frame objects can be nested: that is, an
FO_UnanchoredFrame or FO_AFrame object can be the parent of another
FO_UnanchoredFrame object. Every API graphic object (except an object that
represents a page frame or an anchored frame) is a descendant of exactly one API page
frame object.
Suppose you create a page that contains:


An unanchored frame that contains an oval, a rectangle, and a text frame with some
text in it



A text line that overlaps the unanchored frame, but is drawn directly on the page

FrameMaker products organize the objects as shown in Figure 2-7.

FDK Programmer’s Guide

93

2

Frame Document Architecture

Graphic objects

Draw Order

FP_FirstGraphicInFrame

FO_TextLine
FP_LastGraphicInFrame

FP_LastGraphicInFrame

FP_PrevGraphicInFrame

FP_NextGraphicInFrame

FO_Rectangle

FP_PrevGraphicInFrame

(Page frame)

FP_NextGraphicInFrame

FP_PageFrame

FP_PrevGraphicInFrame

FO_UnanchoredFrame

FO_UnanchoredFrame

FP_NextGraphicInFrame

FP_FirstGraphicInFrame

FO_BodyPage

FO_Ellipse

FO_TextFrame

Figure 2-7 API objects that represent a page and the graphic objects on it

How the API represents groups
The API represents a grouped set of graphic objects with an FO_Group object. It
maintains the objects that constitute a group in a linked list. The FO_Group properties,
FP_FirstGraphicInGroup and FP_LastGraphicInGroup, specify the first and
last objects in the list. Each graphic object has FP_PrevGraphicInGroup and
FP_NextGraphicInGroup properties, which specify the objects before and after it
in the list.
Grouping graphic objects does not affect their position in the linked list of API graphic
objects in a frame. That is, it does not affect their position in the draw order. Group
objects themselves have an arbitrary position in the draw order.

94

FDK Programmer’s Guide

Flows

...

Frame Document Architecture

How the API represents selections of graphic objects
The FO_Doc property, FP_FirstSelectedGraphicInDoc, specifies the ID of the
object that represents the first selected graphic object in a document. If more than one
graphic object is selected, the API forms a linked list of the API graphic objects that
represent the selected graphic objects. API graphic objects have an
FP_NextSelectedGraphicInDoc property that specifies the ID of the next
selected graphic object. The order of the list is not necessarily the same as the order in
which the graphic objects were selected.
Although FP_FirstSelectedGraphicInDoc is a document property, you can
only select graphic objects that are within the same frame.

Flows
FrameMaker products use flows to connect text frames in a document.

What the user sees
A flow tells the FrameMaker product where to put additional text when a text frame is
full. In a simple document, there may be only one flow associated with the body pages.
In complex documents such as newsletters, you may create multiple flows that have
connected text frames on different pages.

VIEWS

1

2

3

Figure 2-8 Multiflow document

Flows have an Autoconnect setting that controls whether the FrameMaker product
generates a new page when you fill the last text frame of a flow. If Autoconnect is on,
the FrameMaker product creates a new page and connects a text frame on the new page
with the text frame on the previous page.

FDK Programmer’s Guide

95

2

Frame Document Architecture

Flows

Main flows
Each document has a main flow. Normally, the FrameMaker product treats the main
flow like any named flow in the document. However, there are cases when the
FrameMaker product treats the main flow specially:


When you generate a table of contents or an index, the FrameMaker product puts the
generated text into the main flow of the generated document.



When you run Compare Documents, the FrameMaker product puts the Summary text
into the main flow.

Usually the main flow is the default flow for the current language. For example, if the
current language is English, the main flow is A.
If there are several Autoconnect flows in the document with the default flow tag, the
main flow is the one in the backmost text frame on the frontmost body page.

How the API represents flows
The API represents a flow with an FO_Flow object, whose properties provide the
following information:


The flow’s format characteristics, such as the feathering and whether Autoconnect is
enabled



The IDs of the first and last FO_TextFrame objects in the flow



The ID of the next FO_Flow object in the document

How the API organizes flows
The API maintains a document’s FO_Flow objects in a linked list.
The FO_Doc property, FP_FirstFlowInDoc, specifies the ID of the first FO_Flow
object in the list. FO_Flow objects have a property named FP_NextFlowInDoc,
which specifies the next FO_Flow object in the list. The order of the list is random; it
does not correspond to the order in which the flows appear in the document.
The API also maintains the objects that represent a flow’s text frames in a linked list.
The FO_Flow properties, FP_FirstTextFrameInFlow and
FP_LastTextFrameInFlow, specify the first and last FO_TextFrame objects in
the list. Each FO_TextFrame object has an FP_PrevTextFrameInFlow property
and a FP_NextTextFrameInFlow property, which specify the previous and next
FO_TextFrame objects in the list. For more information on how flows, text frames,
and paragraphs are organized, see “How the API organizes paragraphs” on page 104.

96

FDK Programmer’s Guide

...

Frame Document Architecture

Flows

Suppose you create the document shown in Figure 2-9. The document has two flows: a
main flow, named A, and a second flow that is unnamed. The A flow connects a twocolumn text frame on the first page and a two-column text frame on the second page.
The unnamed flow appears only on the first page and has only one text frame.

Flow A

A

A

A

A

Unnamed flow

1

2

Figure 2-9 Document with a named and an unnamed flow

Figure 2-10 shows how the API organizes the objects that represent the flows and text
frames shown in Figure 2-9.

FP_NextFlowInDoc

(Unnamed flow)

FO_Doc

FP_FirstTextFrameInFlow
FO_TextFrame
FP_LastTextFrameInFlow

FP_FirstTextFrameInFlow

FO_Flow
FP_MainFlowInDoc

FO_TextFrame

(Flow A)

FP_LastTextFrameInFlow

FP_PrevTextFrameInFlow

FO_Flow

FP_NextTextFrameInFlow

FP_FirstFlowInDoc

FO_TextFrame

Figure 2-10 Objects that represent a document with two flows

FDK Programmer’s Guide

97

2

Frame Document Architecture

Flows

Although the FP_FirstFlowInDoc property specifies the FO_Flow object for the
unnamed flow in Figure 2-10, it could also specify the FO_Flow object that represents
Flow A. The determination of which flow is first in the list is completely random.
The API uses FO_SubCol objects to represent the column formatting of text as follows:


Contiguous paragraphs in each column of a text frame are within a single
FO_SubCol object.



Contiguous paragraphs within sidehead area are within a single FO_SubCol.



Each contiguous series of paragraphs that spans columns and/or sideheads is
represented by a single FO_SubCol object.



Following paragraphs that do not span columns and sideheads begin a new group of
FO_SubCol objects. For example, Figure 14.11 shows a page that has seven
FO_SubCol objects.two groups of three, plus one for the heading that spans all
columns..

The FO_TextFrame properties, FP_FirstSubCol and FP_LastSubCol, specify
the first and last FO_SubCol objects in a specific text frame. Each FO_SubCol
object has an FP_PrevSubCol property and a FP_NextSubCol property, which
specify the previous and next FO_SubCol objects in the flow. Each FO_SubCol
object also has a FP_ParentTextFrame property, which specifies the text frame it
is in. If a text frame has only one column, its FP_FirstSubCol and
FP_LastSubCol properties both specify the ID of the FO_SubCol object that
represents it.
Figure 2-11 shows how the API organizes the objects that represent the two-column text
frame on the first page of the document in Figure 2-9.
FP_FirstSubCol
x tF r

FO_TextFrame

FP_

Pa re

n tT e

x tF r

ame

FP_LastSubCol

FO_SubCol

Figure 2-11 Objects that represent a text frame with two columns

98

FDK Programmer’s Guide

FP_PrevSubCol

n tT e

FP_NextSubCol

Pa re
FP_

FO_SubCol

ame

Flows

...

Frame Document Architecture

In structured FrameMaker, flows can be structured. If a flow is structured, the FO_Flow
object that represents it has a FP_HighestLevelElement property that specifies the
ID of the root element.
For information on how the API organizes paragraphs and text in flows, text frames, and
columns, see “How the API organizes paragraphs” on page 104.

FDK Programmer’s Guide

99

2

Frame Document Architecture

Paragraph Catalog formats

Paragraph Catalog formats
Each document has a Paragraph Catalog containing one or more Paragraph Catalog
formats.

What the user sees
Each Paragraph Catalog format specifies aspects of a paragraph’s appearance, such as
its indents, line spacing, and default font. Each format has a name or tag, which usually
corresponds to a type of paragraph, such as title, body, or heading. To make a
paragraph’s appearance conform to a format, you apply the format to the paragraph.
You can apply the same format to multiple paragraphs to ensure consistency in your
document.
You can add formats to the Paragraph Catalog or modify or delete formats that are
already in it.

How the API represents Paragraph Catalog formats
FrameMaker represents each Paragraph Catalog format with an FO_PgfFmt object,
whose properties provide the following information:


The name of the paragraph format



Formatting information



The ID of the next FO_PgfFmt object in the document

Suppose you create the paragraph format described in the Paragraph Designer in
Figure 2-12.

Figure 2-12 Paragraph Designer

100

FDK Programmer’s Guide

Paragraphs

...

Frame Document Architecture

The API represents this paragraph format with an FO_PgfFmt object. The following
table lists some of its properties.
Property

Type

Value

FP_Name

StringT

Step

FP_AutoNumString

StringT

.\t

FP_AutoNumChar

StringT

""

FP_PgfIsAutoNum

IntT

True

FP_NextPgfFmtInDoc

F_ObjHandleT

ID of the next Paragraph Catalog format
in the document’s list of Paragraph
Catalog formats

The FP_AutoNumChar property specifies the character format to be applied to the
string specified by FP_AutoNumString. When the default font is used,
FP_AutoNumChar is set to a null string ("").
How the API organizes Paragraph Catalog formats
The API organizes the FO_PgfFmt objects in a document in a linked
list. The FO_Doc property, FP_FirstPgfFmtInDoc, specifies the first
FO_PgfFmt object in the list. FO_PgfFmt objects have an FP_NextPgfFmtInDoc
property, which specifies the ID of the next FO_PgfFmt object in the list. The order
of the list does not correspond with the order in which the formats appear in the
Paragraph Catalog.

Paragraphs
A paragraph can be a body of text, a title, or an item in a list.

What the user sees
You can type a paragraph in a text frame, a footnote, or a table cell.
Every paragraph has a paragraph format consisting of:


A tag, which is the name of a format stored in the Paragraph Catalog



Formatting information, which is the same information that a Paragraph Catalog
format provides, such as indents and leading

Every paragraph starts with a tag and formatting information that matches a Paragraph
Catalog format. There are several ways you can change a paragraph’s format:

FDK Programmer’s Guide 101

2

Frame Document Architecture

Paragraphs



Apply a different Paragraph Catalog format to the paragraph.
When you do this, the FrameMaker product changes the paragraph’s formatting
information to match that of the Paragraph Catalog format. This process is known as
tagging.



Change the paragraph’s formatting information.
This does not affect the Paragraph Catalog format that you tagged the paragraph
with. For example, if you tag a paragraph with a tag named indentbody that specifies
a 1-inch indent and subsequently change the paragraph’s indent to 2 inches, the
indentbody format and other paragraphs tagged as indentbody still have a 1-inch
indent. This change is a format override, and it applies only to that paragraph
instance.



Change the Paragraph Catalog format’s formatting information.
FrameMaker products allow you to update all the paragraphs that are tagged with the
format you changed. You can choose whether you want to retain format overrides
when FrameMaker updates all paragraphs in the document with the same tag.

How the API represents paragraphs
FrameMaker products represent each paragraph with an FO_Pgf object, whose
properties provide the following information:


The ID of the text frame and text column containing the paragraph



The paragraph’s formatting information (the same set of properties that a Paragraph
Catalog format provides)



The paragraph’s tag



The IDs of sibling FO_Pgf objects



A flag indicating whether the paragraph has been successfully spell-checked since
the last change was made to it

Each paragraph object also contains an F_TextItemsT structure, which represents
the text in the paragraph. For more information about text and the F_TextItemsT
structure, see “How the API represents text” on page 112.

102

FDK Programmer’s Guide

Paragraphs

...

Frame Document Architecture

Suppose you create the paragraph shown in Figure 2-13.

Figure 2-13 A paragraph

The API represents the paragraph with an FO_Pgf object. The following table lists
some of its properties.
Property

Type

Value

FP_Name

StringT

Step

FP_AutoNumString

StringT

.\t

FP_PgfIsAutoNum

IntT

True

FP_PgfNumber

StringT

1.

FA_LeftIndent

MetricT

0

FP_InTextFrame

F_ObjHandleT

ID of the text frame the
paragraph starts in

FP_InTextObj

F_ObjHandleT

ID of the subcolumn
(FO_SubCol object) the
paragraph starts in

A paragraph’s FP_InTextObj property does not always specify the ID of a
subcolumn. If the paragraph appears in a table cell, it specifies the ID of the FO_Cell
object representing the cell. If the paragraph appears in a footnote, FP_InTextObj
specifies the ID of the FO_Fn object representing the footnote.
How to apply formats to paragraphs
To apply a format from the paragraph format catalog to a specific paragraph object, first
get the ID of the FO_Pgf object in question. Then loop through the document looking
for the FO_PgfFmt object with a name that matches the tag you want to apply to the
paragraph. Then use F_ApiGetProps() to get the list of properties from the
FO_PgfFmt object, and use F_ApiSetProps() to set the property list to the FO_Pgf
in question.

FDK Programmer’s Guide 103

2

Frame Document Architecture

Paragraphs

How the API organizes paragraphs
The API maintains FO_Pgf objects in two linked lists:


The list of all FO_Pgf objects in a document



The list of FO_Pgf objects in a flow

The list of paragraphs in a document
The FO_Doc property, FP_FirstPgfInDoc, specifies the first FO_Pgf object in
the list of FO_Pgf objects in a document. Each FO_Pgf object has an
FP_NextPgfInDoc property, which specifies the next FO_Pgf object in the list. The
order of the list of FO_Pgf objects in a document does not necessarily correspond to
the actual order of the paragraphs in the document.
The list of paragraphs in a flow
FO_Flow objects do not have a property that specifies the first FO_Pgf object in a
flow. To find the first FO_Pgf object in the flow, you must find the first
FO_TextFrame object in the flow. Then you must get the FO_Pgf object specified
by the FO_TextFrame object’s FP_FirstPgf property. In some cases, the first text
frame in the flow may not contain any paragraphs. You must traverse subsequent text
frames and check them to see if they contain any paragraphs.
Each FO_Pgf object has FP_PrevPgfInFlow and FP_NextPgfInFlow
properties, which specify the IDs of the FO_Pgf objects before and after it in the flow.
To get the paragraphs in a flow in order, you traverse these properties.
It is possible for a paragraph to begin in one text frame and end in another. When this
happens, the ID of the FO_Pgf is specified by the FP_LastPgf property of the text
frame in which it begins and the FP_FirstPgf property of the text frame in which it
ends.
Suppose you create two text frames and connect them with a flow. The first text frame
has two paragraphs in it; the second paragraph continues into the next text frame as
shown in Figure 2-14.

Figure 2-14 Flow with two text frames

104

FDK Programmer’s Guide

Paragraphs

...

Frame Document Architecture

The API organizes the objects that represent the flow, text frames, and paragraphs as
shown in Figure 2-15.
FO_Pgf
FP_FirstPgf

(Paragraph 1)

FP_FirstPgf

FO_TextFrame
FP_LastTextFrameInFlow

FO_Pgf

FP_LastPgf

(Paragraph 2)

F_TextItemsT

FP_NextPgfInFlow

FO_Flow

FP_PrevTextFrameInFlow

FP_NextTextFrameInFlow

(Left text frame)

FP_PrevPgfInFlow

FO_TextFrame

(Right text frame)

FP_PrevPgfInFlow

FP_FirstTextFrameInFlow

FP_NextPgfInFlow

F_TextItemsT

FO_Pgf
(Paragraph 3)

FP_LastPgf

F_TextItemsT

Figure 2-15 Objects that represent a flow with text frames and paragraphs

Like text frames, subcolumns (FO_SubCol objects) have FP_FirstPgf and
FP_LastPgf properties, which specify the first and last paragraphs in them. If a
paragraph begins in one text column and ends in another, the paragraph’s ID is specified
by the FP_LastPgf property of the subcolumn in which it begins and the
FP_FirstPgf property of the subcolumn in which it ends.

FDK Programmer’s Guide 105

2

Frame Document Architecture

Character Catalog formats

Character Catalog formats
Each document has a Character Catalog containing one or more character formats.

What the user sees
Each character format has a name (or tag), which usually corresponds to a type of text,
such as Emphasis, Usertype, or Booktitle. It also contains information about how text
should look, such as its font family, weight, and angle. To make the appearance of a set
of characters conform to a Character Catalog format, you apply the format to the set of
characters.
When you apply a character format to a set of characters, it overrides the default font
setting of the paragraph format. If you reapply a Paragraph Catalog format to the
paragraph, it does not affect the format of the characters that you previously tagged with
the character format.
FrameMaker products allow you to create character formats that override only some
properties of the text to which they are applied. To leave one of the current text
properties intact, you set the corresponding character format property to As Is. The
Character Designer indicates the As Is state with the words As Is or a grayed (or
stippled) checkbox.
You can add character formats to the Character Catalog or modify or delete formats that
are already in it.

How the API represents Character Catalog formats
FrameMaker products represent each Character Catalog format with an FO_CharFmt
object, whose properties provide the following information:

106



The name of the character format



Character formatting information, such as the font family, angle, and weight



Whether the character format’s formatting overrides the default formatting of the text
that the format is applied to



The ID of the next FO_CharFmt object in the document

FDK Programmer’s Guide

Character Catalog formats

...

Frame Document Architecture

How the API represents fonts
FO_Session objects have properties (such as FP_FontFamilyNames) that provide
arrays of the names of the font families, variations, angles, and weights available in the
current session. These lists are referenced by F_StringsT structures. F_StringsT
is defined as:
typedef struct {
UIntT len; /* Number of strings */
StringT *val; /* Array of strings */
} F_StringsT;

For example, if Bold and Regular are the only font weights available in the current
session, the fields of the F_StringsT structure specified by the FO_Session
property, FP_FontWeightNames, have the following values:
len: 3
val: {"","Regular","Bold"}

To set a character format’s weight to Bold in this session, you set its FP_FontWeight
property to 2.
For more information on session font properties, see “How the API indicates which
fonts are available in a session” on page 70.
You can also use the following properties to specify a font:


FP_FontPlatformName specifies a font name that uniquely identifies the font on
the Windows platform.



FP_FontPostScriptName specifies the name given to a font when it is sent to a
PostScript printer (specifically, the name that is passed to the PostScript FindFont
operator before any font coordination operations).
The PostScript name is unique for all PostScript fonts, but may not be available for
fonts that have no PostScript version.
For the same Asian font, the PostScript name can be different on different platforms.
This is because they might have slightly different extensions to the character
mappings. For example, Ryumin-Light on the Macintosh is Ryumin-Light83pv-RKSJ-H, while it is Ryumin-Light-90ms-RKSJ-H on a Windows system.
Since these are the same fonts, FrameMaker products will treat these as the same
PostScript name. To do so, FrameMaker products ignore the following keywords in
PostScript names:
83pv
90pv
90ms
Ext

FDK Programmer’s Guide 107

2

Frame Document Architecture

Character Catalog formats

Add
NWP

The FP_FontPlatformName property specifies a platform-specific ASCII string
that uniquely identifies a font for a particular platform. The string consists of several
fields separated by periods.
On Windows, the string you specify for FP_FontPlatformName has the following
syntax:
W.FaceName.ItalicFlag.Weight.Variation
This field

Represents

W

Platform designator

FaceName

Windows face name (for more information, see your Windows
documentation)

ItalicFlag

Whether font is italic; you can use one of the following flags:

I (Italic)
R (Regular)
Weight

Weight classification, for example 400 (Regular) or 700 (Bold)

The following strings are valid representations of the Windows font, Helvetica Narrow
Bold Oblique:
W.Helvetica-Narrow.I.700
W.Helvetica.I.700.Narrow

When reading in a document, a FrameMaker product determines a font name by
checking font properties in the following order:


FP_FontPlatformName



Combination of FP_FontFamily, FP_FontVariation, FP_FontWeight, and
FP_FontAngle



FP_FontPostScriptName

Your clients do not need to use all three methods to change fonts. You should always
specify the PostScript name, if it is available.
How the API represents As Is settings
FO_CharFmt objects use two properties to represent a font characteristic: one to
represent the characteristic’s As Is state and one to represent the characteristic itself.
For example, FP_UseFontWeight specifies whether the character format’s font
weight overrides the default font weight of the text that the format is applied to.

108

FDK Programmer’s Guide

Character Catalog formats

...

Frame Document Architecture

FP_FontWeight specifies the character format’s font weight. If
FP_UseFontWeight is True, the font weight specified by FP_FontWeight
overrides the default font weight for the text. If FP_UseFontWeight is False (As
Is), FP_FontWeight does not affect the text’s font weight.
If an FP_UseCharacteristic property is False, the character format’s property
list includes only the FP_UseCharacteristic property. It doesn’t include the
FP_Characteristic property for the characteristic (since this property is not used).
Suppose you create the character format specified in the Character Designer in
Figure 2-16.

Figure 2-16 Character Designer

The API represents the character format with an FO_CharFmt object. The following
table lists some of its properties.
Property

Type

Value

FP_CharTag

StringT

booktitle

FP_FontAngle

IntT

Index of Italic font angle

FP_UseFontAngle

IntT

True

FP_UseFontFamily

IntT

False

FP_UseFontVariation

IntT

False

FP_UseFontWeight

IntT

False

FP_UseUnderline

IntT

False

FP_FontSize

MetricT

36*pts

FP_UseFontSize

IntT

True

FDK Programmer’s Guide 109

2

Frame Document Architecture

Condition Formats

This character format overrides the default font angle setting and the size of the text to
which it is applied. It does not override any of the text’s other default characteristics.
How the API organizes Character Catalog formats
The API organizes the formats in a document’s Character Catalog in a linked list.
FO_Doc objects have an FP_FirstCharFmtInDoc property that specifies the first
FO_CharFmt object in the list. FO_CharFmt objects have an
FP_NextCharFmtInDoc property, which specifies the ID of the next FO_CharFmt
object in the list. The order of the list does not correspond to the order in which the
formats appear in the Character Catalog.

Condition Formats
FrameMaker products provide condition formats that allow the user to selectively show
or hide text in a document.

What the user sees
To selectively show and hide text, you create a condition format (or tag) and apply it to
selections of text. For example, you can create a condition tag named Comment and
apply it to all the comments you add to a document. You can then instruct the
FrameMaker product to hide all the text with the Comment tag when you print a final
draft of the document. A document can have multiple condition tags.
FrameMaker products allow you to specify a format override, or a special style and
color for a condition. For example, you can make all text tagged with the Comment
condition underlined and red.

How the API represents condition formats
The API represents each condition format with an FO_CondFmt object, whose
properties provide the following information:


The condition name



Whether text tagged with the condition is currently visible



The format overrides



The ID of the next condition format in the document

The API represents the condition setting of a location in text as a text property. For more
information on text properties, see “How the API represents text” on page 112.

110

FDK Programmer’s Guide

Condition Formats

...

Frame Document Architecture

If you choose to hide a condition tag, the FrameMaker product moves text with that tag
to a hidden page and replaces it with markers. For more information on hidden
conditional text, see “How the API represents hidden conditional text” on page 120.
Suppose you create the condition tag specified in the Edit Condition Tag dialog box
shown in Figure 2-17.

Figure 2-17 Edit Condition Tag dialog box

The API represents the condition with an FO_CondFmt object. The following table
lists some of its properties.
Property

Type

Value

FP_Name

StringT

Comment

FP_NextCondFmtInDoc

F_ObjHandleT

ID of next condition in list of
document’s conditions

FP_CondFmtIsShown

IntT

True

FP_SepOverride

F_ObjHandleT

ID of the FO_Color object that
represents red color

FP_StyleOverride

IntT

FV_CN_SINGLE_UNDERLINE

FP_UseSepOverride

IntT

True

How the API organizes condition formats
The API organizes a document’s FO_CondFmt objects in a linked list. The FO_Doc
property FP_FirstCondFmtInDoc specifies the first FO_CondFmt object in the
list. FO_CondFmt objects have a property named FP_NextCondFmtInDoc, which
specifies the ID of the next FO_CondFmt object in the list. The order of the list does
not correspond to the order in which the formats appear in the Conditional Text
window.

FDK Programmer’s Guide 111

2

Frame Document Architecture

Text

Text
The user can type text into a text line or a paragraph in a text frame, table cell, or
footnote.

What the user sees
FrameMaker products allow you to insert things, such as anchored frames, footnotes,
tables, and cross-references into text. The point at which you insert these things is called
an anchor. FrameMaker products represent an anchor with an anchor symbol ) on the
screen. This symbol is not visible if the Text Symbols view option is turned off. The
anchor moves with the text to which it is attached.
All text has a set of properties that specify the following information about it:


A tag, or the name of a character format stored in the Character Catalog



Formatting information (the same information that a Character Catalog format
provides, such as the font family and size)



A set of conditional text formats that apply to it

These properties are called text properties.
Just as you can override a Paragraph Catalog tag by changing an individual paragraph’s
format, you can also override a Character Catalog tag by changing the properties of a
selection of text.
You can also apply one or more conditions to a selection of text. This allows you to hide
or display the text for particular versions of a document.

How the API represents text
The API represents the text in each paragraph or graphic text line with an
F_TextItemsT structure, which is defined as:
typedef struct {
UIntT len; /* The number of text items */
F_TextItemT *val; /* Array of text items */
} F_TextItemsT;

112

FDK Programmer’s Guide

Text

...

Frame Document Architecture

The API represents an individual text item with an F_TextItemT structure, which is
defined as:
typedef struct
{
IntT offset; /* Characters from the beginning */
IntT dataType; /* The type of text item, e.g. FTI_String */
union {
StringT sdata; /* String if type is FTI_String */
IntT idata; /* An ID if the item specifies an object */
} u;
} F_TextItemT;

The offset value specifies the distance between the start of the text item and the
beginning of the text line or paragraph. This distance is measured in the number of
characters (both regular characters and anchor symbols).
Each of the following constitutes a separate text item:


A string of characters with common text properties
A text item can contain a string that is as long as a line of text. However, the API uses
a separate text item for each section of the text that has different text properties. If a
single property (such as the font weight, font angle, or condition format) is different,
the API starts a new text item. So a single line of text may require several text items
to represent it.



The beginning or end of a line, paragraph, flow, column, page, or structural element
The API uses text items to indicate the beginning or end of the various entities that
organize text. Most of these text items specify the ID of an object. Text items that
indicate the end of a line specify whether the line end is a regular, hyphenated, or
hard line end.



An anchor for a table, footnote, marker, cross-reference, variable, or anchored frame
The API represents tables, footnotes, markers, cross-references, variables, and
anchored frames with separate objects. It uses a text item to represent the anchor for
each of these entities. The text item specifies the ID of the object. For example, the
API represents a table with an FO_Tbl object. It uses a table anchor
(FTI_TblAnchor) text item to indicate where the table occurs in the text.



A text properties change
This type of text item identifies the point in text at which the text properties change.
It specifies flags that indicate which text properties differ from the properties of the
text immediately preceding the text item.

FDK Programmer’s Guide

113

2

Frame Document Architecture

Text

The following table lists the values the F_TextItemT.dataType field can have and
the types of data the corresponding text item provides.
Text item type (dataType)

What the text item represents

Text item data

FTI_TextObjId

The object to which the offsets
of all the text items are relative

ID of an FO_Pgf,
FO_Cell,
FO_TextLine,

FO_TiApiClient,
FO_TiFlow,
FO_TiText, or
FO_TiTextTable
FTI_String

A string of characters with the
same condition and character
format

A character string

FTI_LineBegin

The beginning of a line

Nothing

FTI_LineEnd

The end of a line and the line
end type

If the line end is a normal
line end, 0; if it is a forced
line end, the

FTI_HardLineEnd
flag is set; if it is a hyphen
line end, the

FTI_HyphenLineEnd
flag is set
FTI_PgfBegin

The beginning of a paragraph

ID of an FO_Pgf

FTI_PgfEnd

The end of a paragraph

ID of an FO_Pgf

FTI_FlowBegin

The beginning of a flow

ID of an FO_Flow

FTI_FlowEnd

The end of a flow

ID of an FO_Flow

FTI_PageBegin

The beginning of a page

ID of an

FO_BodyPage,
FO_HiddenPage,
FO_MasterPage,
FO_RefPage
FTI_PageEnd

The end of a page

ID of an

FO_BodyPage,
FO_HiddenPage,
FO_MasterPage,
FO_RefPage
FTI_TextFrameBegin

The beginning of a text frame

ID of an

FO_TextFrame
FTI_TextFrameEnd

The end of a text frame

ID of an

FO_TextFrame

114

FDK Programmer’s Guide

Text

...

Frame Document Architecture

Text item type (dataType)

What the text item represents

Text item data

FTI_SubColBegin

The beginning of a column

ID of an FO_SubCol

FTI_SubColEnd

The end of a column

ID of an FO_SubCol

FTI_FrameAnchor

An anchored frame

ID of an FO_AFrame

FTI_FnAnchor

A footnote

ID of an FO_Fn

FTI_TblAnchor

A table

ID of an FO_Tbl

FTI_MarkerAnchor

A marker

ID of an FO_Marker

FTI_XRefBegin

The beginning of a crossreference instance

ID of an FO_XRef

FTI_XRefEnd

The end of a cross-reference
instance

ID of an FO_XRef

FTI_VarBegin

The beginning of a variable
instance

ID of an FO_Var

FTI_VarEnd

The end of a variable instance

ID of an FO_Var

FTI_TextInsetBegin

The beginning of a text inset

ID of an

FO_TiApiClient,
FO_TiFlow,
FO_TiText, or
FO_TiTextTable
FTI_TextInsetEnd

The end of a text inset

ID of an

FO_TiApiClient,
FO_TiFlow,
FO_TiText, or
FO_TiTextTable
FTI_ElementBegin

The beginning of a container
element

ID of an FO_Element

FTI_ElementEnd

The end of a container element

ID of an FO_Element

FTI_ElemPrefixBegin

The beginning of an element’s
prefix

ID of an FO_Element

FTI_ElemPrefixEnd

The end of an element’s prefix

ID of an FO_Element

FTI_ElemSuffixBegin

The beginning of an element’s
suffix

ID of an FO_Element

FTI_ElemSuffixEnd

The end of an element’s suffix

ID of an FO_Element

FTI_CharPropsChange

A change in the text properties

Flags indicating which
properties have changed
(see the table below)

FDK Programmer’s Guide

115

2

Frame Document Architecture

Text

Text item type (dataType)

What the text item represents

Text item data

FTI_RubiComposite
Begin

The beginning of a rubi
composite (and the beginning of
oyamoji text).

ID of an FO_Rubi

FTI_RubiComposite
End

The end of a rubi composite.

ID of an FO_Rubi

FTI_RubiTextBegin

The beginning of rubi text (and
the end of oyamoji text).

ID of an FO_Rubi

FTI_RubiTextEnd

The end of rubi text.

ID of an FO_Rubi

The following table lists the bit flags that a client can bitwise AND with the idata
field of an FTI_CharPropsChange text item and the types of text property changes
each flag indicates. For example, to determine if the font family changed, bitwise AND
the FTF_FAMILY flag with the idata field.

116

Flag

Meaning

FTF_FAMILY

The font family has changed.

FTF_VARIATION

The font variation has changed.

FTF_WEIGHT

The font weight has changed.

FTF_ANGLE

The font angle has changed.

FTF_UNDERLINING

The underlining has changed.

FTF_STRIKETHROUGH

The strikethrough characteristic has changed.

FTF_OVERLINE

The overline characteristic has changed.

FTF_CHANGEBAR

The change bars have changed.

FTF_OUTLINE

The outline characteristic has changed.

FTF_SHADOW

The shadow characteristic has changed.

FTF_PAIRKERN

The pair kerning has changed.

FTF_SIZE

The font size has changed.

FTF_KERNX

The kern-x characteristic has changed.

FTF_KERNY

The kern-y characteristic has changed.

FTF_SPREAD

The font spread has changed.

FTF_COLOR

The color has changed.

FTF_CHARTAG

The Character Catalog format has changed.

FDK Programmer’s Guide

Text

...

Frame Document Architecture

Flag

Meaning

FTF_CAPITALIZATION

The capitalization has changed.

FTF_POSITION

The character position has changed.

FTF_CONDITIONTAG

The condition tag has changed.

FTF_STRETCH

Font stretch value has changed

FTF_LANGUAGE

Character language has changed

FTF_TSUME

Tsume setting has changed

FTF_IIF

An internal flag having to do with asian text. input. If there is a
non-zero value for this flag, a front end processor is controlling
that text; you should not modify the associated text item.

FTF_ENCODING

The text encoding has changed.

FTF_ALL

OR of all the flags listed above.

Figure 2-18 shows a paragraph and the text items the API uses to represent the
paragraph’s text.

offset: 0

offset: 0

offset: 0

offset: 5

offset: 5

offset: 17

dataType:
FTI_PgfBegin

dataType:
FTI_LineBegin

dataType:
FTI_String

dataType:
FTI_CharPropsChange

dataType:
FTI_String

dataType:
dataType:
FTI_Marker-Anchor FTI_LineEnd

sdata: "This "

idata: ID of
FO_Pgf

idata:
FTF_WEIGHT

sdata: "is a marker." idata: ID of
FO_Marker

offset: 18

idata: 0

offset: 18
dataType:
FTI_PgfEnd
idata: ID of FO_Pgf

Figure 2-18 Paragraph text and the text items that represent it

There are several important things to note about the text items shown in Figure 2-18:


Because the string "This " and the string "is a marker." have different font
weights, there are separate text items for them.



The FTI_CharPropsChange text item indicates that the text properties have
changed; the FTF_WEIGHT flag that it specifies indicates that the font weight has
changed.

FDK Programmer’s Guide

117

2

Frame Document Architecture

Text



The marker anchor is counted in the offset.

How the API represents special characters
The API uses the FrameMaker product character set. Some characters are either
reserved by the C language or belong to the higher ASCII range. To represent these
characters in a string, use octal (\) or hexadecimal (\x) sequences.

Character

Hexadecimal
representation

Octal
representation

>

\x3e

\76

" (straight double quotation mark)

\x22

\42

“ (left curved quotation mark)

\xd2

\322

” (right curved quotation mark)

\xd3

\323

For a complete list of the characters in the FrameMaker product character set and the
corresponding hexadecimal codes, see your Frame product user’s manual. If you are
using ANSI C, you can use these hexadecimal codes or their octal equivalents. If you
are not using ANSI C, you must use octal (\) sequences.
Suppose you want to represent the following text in the API:
This is an em dash —

If you are not using ANSI C, you must specify the string This is an em dash
\321. If you are using ANSI C, you can also specify the string This is an em dash
\xd1.
How the API represents text properties
The FTI_CharPropsChange text item only indicates that particular text properties
have changed. It does not indicate what they have changed to. The API provides a
function named F_ApiGetTextProps(), which allows you to retrieve the text
properties for individual characters in text. You cannot retrieve the text properties for a
range or selection of text, because they may be different for individual characters within
the selection. You can, however, set the text properties for a range of text. For examples
of how to get and set text properties, see “Getting and setting text formatting” on
page 334.

118

FDK Programmer’s Guide

Text

...

Frame Document Architecture

Suppose you retrieve the text properties at the insertion point shown in Figure 2-19.

Figure 2-19 Text containing insertion point

FDK Programmer’s Guide

119

2

Frame Document Architecture

Text

The following are some of the properties of the text at the insertion point.
Property

Type

Value

FP_CharTag

StringT

booktitle

FP_FontFamily

IntT

Index of Times font (for more information on font
name indexes, see “How the API indicates which fonts
are available in a session” on page 70)

FP_FontWeight

IntT

Index of Bold font weight

FP_FontAngle

IntT

Index of Regular font angle

FP_InCond

F_IntsT

NULL

If the conditions Comment and MyComment are applied to the text location, the
FP_InCond property specifies an F_IntsT structure with the following values:
len: 2
val: { Comment_ID, MyComment_ID }

where Comment_ID and MyComment_ID are the IDs of the FO_CondFmt objects
that represent the Comment and MyComment condition formats.
How the API represents hidden conditional text
The user can choose to hide all the text with a specified condition format. If a document
has hidden conditional text, the FrameMaker product automatically adds a hidden page
to it. This hidden page is completely invisible to the user. It has a single flow, named
HIDDEN.
When the user chooses to hide text with a condition format, the FrameMaker product
removes each block of text with that condition format and inserts a Conditional Text
marker (type 10) in its place. This marker text consists of a plus sign (+) and a five-digit
integer. The FrameMaker product places the blocks of hidden text in the HIDDEN text
flow on the hidden page. The text begins with a Conditional Text marker containing a
minus sign (?) and the integer. It ends with another Conditional Text marker containing
an equal sign (=) and the integer. If the hidden conditional text doesn’t span paragraphs,
it appears in one paragraph. If the hidden conditional text spans paragraphs, each
paragraph of conditional text constitutes a separate paragraph in the HIDDEN flow.

120

FDK Programmer’s Guide

Text

...

Frame Document Architecture

Suppose you have a body page with some conditional text and some unconditional text.
The condition tag’s format overrides specify that the text appears underlined, as shown
in Figure 2-20.

Figure 2-20 Body page with conditional and unconditional text

If you hide the text, the body page appears as shown in Figure 2-21.
Marker text: +84974

Marker text: +95675

Marker text: +93024

Figure 2-21 Body page with the conditional text hidden

If you could see the hidden page and the text in the HIDDEN flow, it would appear as
shown in Figure 2-22. The numbers in the markers that represent the hidden conditional
text on the body page correspond to the numbers in the markers on the hidden page.
Marker text: -84974
Marker text: -95675
Marker text: -93024

Marker text: =84974
Marker text: =95675
Marker text: =93024

Figure 2-22 Hidden conditional text on the hidden page

FDK Programmer’s Guide 121

2

Frame Document Architecture

Markers

Markers
Markers are anchored objects that store data and associate that data with specific
locations in the text. Various features in FrameMaker may refer to a marker, or you can
use markers to store data for your FDK clients.

What the user sees
You can use markers to mark entries for a table of contents or an index. A marker’s
position in text is indicated by a marker symbol. A marker contains text, which appears
in the Marker window when you select the marker and choose Marker from the Special
menu.
Any number of marker types can be defined for a document; 11 of them are predefined
by the FrameMaker product as a standard list of marker types, and the others are defined
by the user. The list of defined marker types is saved with the document.

How the API represents markers
The API represents each marker with the following:


An FTI_MarkerAnchor text item that specifies the ID of an FO_Marker object



An FO_Marker object

FO_Marker properties provide the following information:


The marker type; the Id of an FO_MarkerType object



The text the marker contains



The ID of the next FO_Marker object in the document



The location of the marker in text



The element ID of the marker, if it is a structured marker in a structured document



If included, the number of a marker type in versions earlier than 5.5; when opening
the document in FrameMaker 5.5, this maps the old numbered marker type to the
new named bmarker type

FO_MarkerType properties provide the following information:

122



The ID of the next FO_MarkerType object in the document



The name of the marker type, as it appears in the user interface



The internal name of the marker type (usually the same as the name that appears in
the user interface)

FDK Programmer’s Guide

Markers

...

Frame Document Architecture



If included, the number of a marker type in versions earlier than 5.5; when opening
the document in FrameMaker 5.5, this maps the old numbered marker type to the
new named marker type



Whether the marker type appears in the user interface, whether it is saved with the
document, and whether the marker type can be deleted

The FO_Doc property, FP_MarkerTypeNames, specifies an F_StringsT
structure, which provides the list of marker types available in the current document. The
document object also has an FP_FirstMarkerTypeInDoc property as an entry into
the document’s list of marker types.
Given a marker type name, you can use F_ApiGetNamedObject() to get the ID of
the associated FO_MarkerType. The following code returns the ID of the index marker
type:
...
F_ObjHandleT docId, markerId;

/* Get ID of the active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);

markerId = F_ApiGetNamedObject(docId, FO_MarkerType, (StringT)
"Index");
...

Figure 2-23 shows an index marker anchor and the text item that represents it.

offset: 40
dataType: FTI_MarkerAnchor

idata:

FO_Marker ID

Figure 2-23 A marker anchor and the text item that represents it

FDK Programmer’s Guide 123

2

Frame Document Architecture

Markers

The following table lists some of the properties of the FO_Marker object specified by
FTI_MarkerAnchor in Figure 2-23.
Property

Type

Value

FP_MarkerTypeId

F_ObjHandleT

ID of the FO_MarkerType for "Index"

FP_MarkerText

StringT

presidents:past

FP_NextMarkerInDoc

F_ObjHandleT

ID of the next FO_Marker object in
the document

Adding marker types to documents
To add a marker type to a document, use F_ApiNewNamedObject(). Once you have
the new marker type’s ID, you can set any properties that you want to be different from
the default values.
...
F_ObjHandleT docId, myMarkerTypeId;

/* Get ID of the active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);

/* Create the marker type. */
myMarkerTypeId = F_ApiNewNamedObject(docId, FO_MarkerType,
(StringT) "MyMarkerType");
...

To delete a marker type from a document, pass the document ID and the marker type ID
to F_ApiDelete().

Mapping old marker types to named marker types
In versions of FrameMaker earlier than 5.5, marker types were identified by number.
Type 1 through Type 10 were reserved for FrameMaker, and given specific names;
Header/Footer $1, Header/Footer $2, etc. Type 11 through Type 25 were for custom
marker types.
FO_MarkerType and FO_Marker objects have an FP_OldTypeNum property that
maps the named marker type to what was a numbered marker type in earlier documents.
In this way, you can ensure that your client handles markers in legacy data the way you
want.

124

FDK Programmer’s Guide

Cross-reference formats

...

Frame Document Architecture

For example, assume your client adds a marker type named MyMarkerType to a
document, and you set the FP_OldTypeNum property of MyMarkerType to 11. The
user might import or paste text from an older document into the document with
MyMarkerType. If the older text has markers of type 11 in it, they will come into the
new document as MyMarkerType.

The standard list of marker types
Every document includes a set of required marker types; Header/Footer $1,
Header/Footer $2, Index, Comment, Subject, Author, Glossary, Equation, Hypertext
Cross-Ref, and Conditional Text. These are required markers, and cannot be deleted.
You can add an existing public marker type to the standard list by setting the name
string to the FP_AddMarkerTypeToStandardMarkers property of the current
session object. Once you add a marker type to this list, it remains for the entire session;
you must quit the session to remove it.
...
F_ApiSetInt(0, FV_SessionId, FP_OldTypeNum, (IntT) 17);
F_ApiSetString(0, FV_SessionId,
FP_AddMarkerTypeToStandardMarkers, (StringT)
"MyMarkerType");
...

This example first sets a session integer for FP_OldTypeNum to 17. This ensures that
for the rest of the current session, markers of type 17 (from earlier documents) will
come into new documents as markers of type MyMarkerType.
If the the FP_OldTypeNum you specify is taken, your new marker type will not be
added to the list of standard marker types. To confirm that your marker type was added
to the standard list, get the FP_MarkerNames property from the FV_SessionId
object.
It’s possible for the FP_OldTypeNum you specified to be taken; another API client may
have already used that value when assigning a marker type to the standard list. For
example, HTML export in FrameMaker 5.5 is performed by a client that adds the
HTML Macro marker type to the standard list. The value of that marker’s
FP_OldTypeNum is 11. After that client is initialized, no other clients can use the same
value for FP_OldTypeNum when assigning a marker to the standard list.

Cross-reference formats
When you insert a cross-reference in a document, you choose a cross-reference format
that specifies the information provided by the cross-reference.

FDK Programmer’s Guide 125

2

Frame Document Architecture

Cross-reference formats

What the user sees
A cross-reference format consists of a combination of text and cross-reference building
blocks. Cross-reference building blocks are variables that provide information, such as
the current page number or filename.
Each document has a catalog of cross-reference formats. You can add or delete formats
from this catalog.

How the API represents cross-reference formats
FrameMaker products represent each cross-reference format with an FO_XRefFmt
object, whose properties provide the following information:


The name of the cross-reference format



A string containing the cross-reference’s text and cross-reference building blocks



The ID of the next FO_XRefFmt object in the document

Suppose you create a cross-reference format named See Heading & Page as shown in
Figure 2-24.

Figure 2-24 A cross-reference format

126

FDK Programmer’s Guide

Cross-references

...

Frame Document Architecture

The following table lists some properties of the FO_XRefFmt object that represents
this cross-reference format.
Property

Type

Value

FP_Name

StringT

See Heading & Page

FP_Fmt

StringT

See \’<$paratext>\’ on
page\ <$pagenum>.

FP_NextXRefFmtInDoc

F_ObjHandleT

ID of the next FO_XRefFmt object
in the document

Cross-references
A cross-reference refers to a specific location, known as a source, within the current
document or another document. The source can be either a cross-reference marker (a
type 9 marker) or a unique string of text.

What the user sees
When you insert a cross-reference, you select a cross-reference format, which specifies
the information provided by the cross-reference. For more information on crossreference formats, see “Cross-reference formats” on page 125.

How the API represents cross-reference instances
The API represents each cross-reference instance with the following:


FTI_XRefBegin and FTI_XRefEnd text items that specify the ID of the
FO_XRef object



An FTI_String text item, which provides the text that appears where the
cross-reference is inserted



An FO_XRef object

FO_XRef properties provide the following information:


The ID of an FO_XRefFmt object



The ID of the next FO_XRef object in the document



The name of the file in which the cross-reference source is located



The element ID of the cross-reference, if it is in a structured flow in a document

FDK Programmer’s Guide 127

2

Frame Document Architecture

Cross-references

Suppose you insert the cross-reference shown in Figure 2-25, using the See Heading &
Page cross-reference format shown in Figure 2-24.

offset: 0

offset: 0

offset: 1

offset: 47

dataType:
FTI_MarkerAnchor

dataType: FTI_XRefBegin

dataType: FTI_String

dataType: FTI_XRefEnd

idata: FO_XRef ID

sdata: "See \xd2This heading is idata: FO_XRef ID
the x-ref source\ xd3 on
page\x11 1."

idata:

FO_Marker

ID

Figure 2-25 A cross-reference and the text items that represent it

The following are some properties of the FO_XRef object that represents the crossreference.
Property

Type

Value

FP_XRefFmt

F_ObjHandleT

ID of the FO_XRefFmt object
representing the See Heading & Page crossreference format

FP_NextXRefInDoc

F_ObjHandleT

ID of the next FO_XRef object in
document

FP_XRefFile

StringT

An empty string ("")

Client-owned cross references
A client can use the following properties of the FO_XRef object for identifying the
cross-references it owns and to handle them specifically, as required:


FP_XRefClientName



FP_XRefClientType



FP_XRefSrcElemNonUniqueId



FP_XRefAltText.

A client can create its own dialog for cross-references. The notification
FA_Note_DisplayClientXRefDialog is sent to the client to display or update (in
case it is already displayed) this dialog. If the client displays or updates its crossreference dialog, then it sets the return value as FR_DisplayedXRefDialog using the
API, F_ApiReturnValue() to indicate this to FrameMaker. If the return value is not

128

FDK Programmer’s Guide

Variable formats

...

Frame Document Architecture

set as explained, FrameMaker assumes that the client did not display any dialog.
Consequently, FrameMaker’s standard cross-reference dialog is displayed.

Variable formats
The user can insert variables that represent a variety of information, such as the page
number or the date, into text. The information a variable provides is specified by a
variable format.

What the user sees
Each variable format can specify a combination of text and building blocks. Building
blocks are FrameMaker product-defined variables that you can string together.

FDK Programmer’s Guide 129

2

Frame Document Architecture

Variable formats

There are six principal classes of variable formats:


Page number



Date



Filename



Table



Running header or footer



User

Each of these classes has a unique set of building blocks. You cannot use a building
block from one class in another class. For example, you cannot use a date building block
in a page number variable format.

How the API represents variable formats
FrameMaker products represent each variable format with an FO_VarFmt object,
whose properties provide the following information:


The name of the variable format



The list of building blocks and text strings



The type of variable it is (for example, page count or user variable)



ID of the next FO_VarFmt object in the document

Suppose you edit the Creation Date (Long) variable format so that its definition is as
shown in Figure 2-26.

Figure 2-26 Creation Date (Long) variable definition

130

FDK Programmer’s Guide

Variables

...

Frame Document Architecture

The following are some properties of the FO_VarFmt object that represents the
Creation Date (Long) variable format.
Property

Type

Value

FP_Fmt

StringT

<$monthname> <$daynum>,
<$year>

FP_SystemVar

IntT

FV_VAR_CREATION_DATE_LONG

FP_NextVarFmtInDoc

F_ObjHandleT

ID of next FO_VarFmt object in the
document

Variables
The user can insert variables in text. There are some restrictions on inserting some
variable formats. For example, you can insert current page number, running header, and
running footer variables only in an untagged flow on a master page.

What the user sees
The information an instance of a variable provides depends on its variable format. For
example, if a variable’s format is Page Count and the current document has 27 pages,
each time the variable occurs in text, it appears
as 27.

How the API represents instances of variables
The API represents each variable instance with the following:


An FTI_VarBegin text item and an FTI_VarEnd text item that specify the ID
of an FO_Var object



An FTI_String text item that provides the text that appears where the variable is
inserted



An FO_Var object

FO_Var properties provide the following information:


The ID of an FO_VarFmt object



ID of the next FO_Var object in the document



The element ID of the variable, if it is a structured variable in a document

FDK Programmer’s Guide 131

2

Frame Document Architecture

Footnotes

Figure 2-27 shows an instance of the Creation Date (Long) variable and the text items
that represent it.

offset: 0

offset: 1

offset: 8

dataType: FTI_VarBegin

dataType: FTI_String

dataType: FTI_VarEnd

idata: FO_Var ID

sdata: "December 10, 1992"

idata: FO_Var ID

Figure 2-27 A variable instance and the text items that represent it

The following table lists some of the properties of the FO_Var object specified by
FTI_VarBegin and FTI_VarEnd in Figure 2-27.
Property

Type

Value

FP_VarFmt

F_ObjHandleT

ID of the FO_VarFmt object that
represents the Creation Date (Long)
variable format

FP_NextVarInDoc

F_ObjHandleT

ID of the next FO_Var object in the
document

Footnotes
A footnote is a type of special text column that appears at the bottom of a page.

What the user sees
A footnote reference (or anchor) appears in the main text as a number, letter, or special
character. A footnote is visually separated from the main text by a separator (usually a
horizontal line).
The Footnote Properties dialog box allows you to change characteristics that apply to all
the footnotes in a document, such as the type of numbering or special characters used to
represent the anchor and the height of the footnote column.

How the API represents footnotes
When the user chooses the Footnote command, the FrameMaker product inserts a
footnote anchor. It also creates a text frame with invisible borders at the bottom of the
text frame in which the footnote was inserted. The user types the footnote text into the
footnote text frame.

132

FDK Programmer’s Guide

Footnotes

...

Frame Document Architecture

Characteristics, such as the footnote anchor’s numbering type, are represented as
document properties because they apply to all the footnotes in a document and not just
individual footnote instances. For more information on the document properties that
govern footnote characteristics, see “How the API represents documents” on page 74.
The API represents each footnote anchor with an FTI_FnAnchor text item, which
specifies the ID of the FO_Fn object that represents the footnote. FO_Fn properties
provide the following information:


The footnote number



The ID of the text frame in which the footnote text appears



The ID of the next footnote in the list of footnotes in the document



The IDs of the first and last paragraphs containing the footnote’s text



The element ID of the footnote, if it is a structured footnote in a document

Figure 2-28 shows a footnote and the text item that represents it.

offset: 17
dataType: FTI_FnAnchor
idata: FO_Fn ID

Figure 2-28 A footnote and the text item that represents it

FDK Programmer’s Guide 133

2

Frame Document Architecture

Ruling Formats

The following table lists the properties of the FO_Fn object specified by the
FTI_FnAnchor text item in Figure 2-28.
Property

Type

Value

FP_InTextObj

F_ObjHandleT

The ID of the subcolumn (FO_SubCol) in
which the footnote appears.

FP_FnNum

IntT

0.

FP_PrevFn

F_ObjHandleT

ID of the previous footnote in the text frame (in
this case, NULL).

FP_NextFn

F_ObjHandleT

ID of the next footnote in the text frame (in this
case, NULL).

FP_NextFnInDoc

F_ObjHandleT

ID of the next footnote in the document.

FP_FirstPgf

F_ObjHandleT

ID of the first paragraph (FO_Pgf) in the
footnote.

FP_LastPgf

F_ObjHandleT

ID of the last paragraph (FO_Pgf) in the
footnote (in this example, it is the same as the
one specified by FP_FirstPgf).

Although FP_FnNum specifies an integer, the number that appears in the document can
be one of several ordinal or special characters. For example, if you set the document’s
FP_FnNumStyle property to FV_FN_NUM_ALPHA_UC, an A would appear instead of
the 1 in the body text and at the beginning of the footnote.
To get all the paragraphs in a footnote, you traverse the FP_NextPgfInFlow and
FP_PrevPgfInFlow properties, just as you would to get the paragraphs in any other
flow.

Ruling Formats
Each document has a Ruling Catalog containing several ruling formats.

What the user sees
Rulings are the lines that border a table cell or an entire table. A ruling format specifies
a line type (such as Thin or Thick) and the gap between the line and the cell contents.

134

FDK Programmer’s Guide

Ruling Formats

...

Frame Document Architecture

You can specify rulings for an entire table in the Table Designer or for individual table
cells in the Custom Ruling and Shading dialog box. FrameMaker products provide
default rulings, such as Thick and Thin. You can change these rulings or create your
own.

How the API represents ruling formats
The API represents a ruling format with an FO_RulingFmt object, whose properties
provide the following information:


The name of the ruling format



Its line width



The gap between lines if the ruling specifies double lines



The ID of the next FO_RulingFmt object in the document

Suppose you create the Medium ruling format shown in Figure 2-29.

Figure 2-29 Medium ruling format

The API represents this ruling format with an FO_RulingFmt object. The following
table lists some of its properties.
Property

Type

Value

FP_Name

StringT

Medium

FP_RulingPenWidth

MetricT

2*pts

FP_RulingGap

MetricT

0

FP_RulingLines

IntT

2

FDK Programmer’s Guide 135

2

Frame Document Architecture

Table Catalog formats

How the API organizes ruling formats
The API organizes the FO_RulingFmt objects in a document in a linked list. The
FO_Doc property, FP_FirstRulingFmtInDoc, specifies the first FO_RulingFmt
object in the list. Each FO_RulingFmt object has an FP_NextRulingFmtInDoc
property, which specifies the ID of the next FO_RulingFmt object in the list. The
order of the list does not correspond to the order in which the formats appear in the
Custom Ruling and Shading dialog box.

Table Catalog formats
Each document has a Table Catalog containing table formats.

What the user sees
When you create a new table, you specify a format from the Table Catalog. The format
provides the following information:


The Table Catalog format name



Format characteristics, such as the table position, alignment, and rulings



The number of columns and rows

If you tag an existing table with a Table Catalog format, the Table Catalog format
provides only the format name and the format characteristics for the table; it does not
affect the number of columns or rows.
After you have created a new table or tagged an existing table, you can change the
number of columns or rows or the format without affecting the Table Catalog tag. You
can also instruct the FrameMaker product to apply the changes to the Table Catalog tag
and other tables tagged with the format. You can modify or delete formats that are
already in the Table Catalog, or you can add new formats.

136

FDK Programmer’s Guide

Table Catalog formats

...

Frame Document Architecture

How the API represents Table Catalog formats
FrameMaker products represent each Table Catalog format with an FO_TblFmt
object, whose properties provide the following information:


The name of the table format



Format characteristics



The default number of initial columns and rows



The ID of the next FO_TblFmt object in the document

Suppose you create the Table Catalog format described in the Table Designer and the
Insert Table dialog box in Figure 2-30.

Figure 2-30 Table Catalog format

FDK Programmer’s Guide 137

2

Frame Document Architecture

Tables

The following table lists some of the properties of the FO_TblFmt object that
represents Format A.
Property

Type

Value

FP_Name

StringT

Format A

FP_TblInitNumCols

IntT

5

FP_TblInitNumHRows

IntT

1

FP_TblColRuling

F_ObjHandleT

ID of FO_RulingFmt object
that represents the Thin line ruling

FP_TblBodyRowRuling

F_ObjHandleT

ID of FO_RulingFmt object
that represents the Thin line ruling

FP_TblHFSeparatorRuling

F_ObjHandleT

ID of FO_RulingFmt object
that represents the Double line
ruling

How the API organizes Table Catalog formats
The API organizes the formats in the Table Catalog in a linked list.
The FO_Doc object property, FP_FirstTblFmtInDoc, specifies the ID
of the first FO_TblFmt object in the list. Each FO_TblFmt object has
an FP_NextTblFmtInDoc property, which specifies the ID of the next FO_TblFmt
object in the list. The order of the list does not correspond to
the order in which the formats appear in the Table Designer.

Tables
FrameMaker products allow you to insert tables into text. When you insert a table, a
table anchor symbol () appears on the screen at the point where you inserted it.

What the user sees
Tables are useful for organizing information in cells arranged in rows and columns.
Tables can have titles and heading, body, and footing rows. FrameMaker products
automatically repeat table titles and heading and footing rows on each page of a table.
Each cell in a table is actually a type of text frame. It can contain text and nearly
anything you insert in text, such as an anchored frame or a marker. You cannot insert
another table directly into a table cell.
Like a paragraph, each table has a tag and a format. The tag is the name of a Table
Catalog format. A table format specifies the layout characteristics of a table, such as its

138

FDK Programmer’s Guide

Tables

...

Frame Document Architecture

position in a text frame, its alignment, and the rulings and shadings of its columns and
rows. The table format can specify different rulings for the different types of rows (for
example, the body, heading, and footing rows).
You can override a Table Catalog format by changing an individual table’s format. You
can also override an individual table’s format by specifying a custom ruling, shading, or
color for an individual cell or set of cells in the table. If you retag a table with a Table
Catalog format after you have specified custom ruling for some of its cells, it does not
affect the custom ruling for those cells.

How the API represents tables
The API represents a table anchor with an FTI_TblAnchor text item. For more
information on text items, see “How the API represents text” on page 112. Each
FTI_TblAnchor text item specifies the ID of an FO_Tbl object.
The API represents the table itself with the following objects:


An FO_Tbl object



One or more FO_Row objects



One or more FO_Cell objects

FO_Tbl and table formats
FO_Tbl properties provide the following information:


The table format tag (name)



Formatting (such as alignment and rulings)



The number of columns and rows



The ID of the paragraph in the table’s title



IDs of FO_Row objects that represent the first and last rows in the table



ID of the next FO_Tbl object in the document



The element IDs of the table, table title, table heading, table body, table footing
elements if the table is a structured table in a document

FO_Tbl formatting properties are the same as FO_TblFmt formatting properties,
except they do not include properties (such as FP_TblInitNumHRows) that specify
the initial numbers of rows or columns.
The table title
If a table has a title, the FO_Tbl properties, FP_FirstPgf and FP_LastPgf,
specify the IDs of the first and last FO_Pgf objects in the title.

FDK Programmer’s Guide 139

2

Frame Document Architecture

Tables

Rows
The API represents each row in a table with an FO_Row object. FO_Row properties
provide the following information about a table row:


Its type (heading, body, or footing)



Whether it is kept with the previous row, the next row, or both when a page break
occurs within the table



Its maximum and minimum allowable height



The IDs of the FO_Row objects that represent the rows before and after it in the table



The ID of the FO_Cell object that represents the first (leftmost) cell in the row



The conditions that apply to the row



The element ID of the row, if it is a structured row in a document

If a row has conditions applied to it, its FP_InCond property specifies an F_IntsT
structure that includes the IDs of the FO_CondFmt objects that represent the
conditions.
Cells
The API represents each cell in a table with an FO_Cell object, whose properties
provide the following information:


The ruling and shading that the cell inherits from the table format



Custom ruling and shading



Flags that indicate whether the cell’s custom shading and fill override the table’s
shading and fill



IDs of sibling FO_Cell objects



IDs of the first and last paragraphs in the cell



The element ID of the cell, if it is a structured cell in a FrameMaker document

The FO_Cell object properties, FP_FirstPgf and FP_LastPgf, specify
the IDs of the first and last paragraphs in the cell. If there is more than
one paragraph in the cell, each paragraph’s FP_PrevPgfInFlow and
FP_NextPgfInFlow properties specify the IDs of the paragraphs before
and after it.
FO_Cell objects have two properties for each ruling. For example, the properties for
the top ruling are FP_CellDefaultTopRuling and
FP_CellOverrideTopRuling. The default ruling is the ruling that the cell inherits
from the FO_Tbl object that contains it. For example, the
FP_CellDefaultTopRuling property for a cell in a body row inherits the value of
the FP_TblBodyRowRuling property in the FO_Tbl object that contains it. An
140

FDK Programmer’s Guide

Tables

...

Frame Document Architecture

override ruling is a ruling that the user specifies in the Custom Ruling and Shading
dialog box for an individual cell. If a value is specified for an override ruling, it
overrides the default ruling.
The FO_Cell properties, FP_CellOverrideShading and
FP_CellOverrideFill, specify the cell’s custom shading and fill. If the cell’s
custom shading and fill override the table’s default shading and fill,
FP_CellUseOverrideFill and FP_CellUseOverrideShading are True.
How the API organizes the objects that represent tables
Figure 2-31 shows a table anchor, a table, and the text item that represents the anchor.

offset: 0
dataType:
FTI_TblAnchor

sdata:

NULL

Figure 2-31 A table and the text item that represents its anchor

FDK Programmer’s Guide 141

2

Frame Document Architecture

Tables

The API represents the table with the objects shown in Figure 2-32.
FP_FirstRowInTbl

FP_FirstCellInRow

FO_Row

FP_FirstPgf

FO_Cell

(Heading Row)

FO_Pgf

(R1-C1)

FP_PrevCellInRow

FP_NextCellInRow

FP_PrevRowInTbl

FP_NextRowInTbl

FP_LastPgf

FP_FirstPgf

FO_Cell

FO_Pgf

(R1-C2)

FP_LastPgf

FP_FirstCellInRow

FO_Row

FO_Tbl

FP_FirstPgf

FO_Cell

(Body Row)

FO_Pgf

(R2-C1)

FP_PrevCellInRow

FP_NextCellInRow

FP_PrevRowInTbl

FP_NextRowInTbl

FP_LastPgf

FP_FirstPgf

FO_Cell

FO_Pgf

(R2-C2)

FP_LastPgf

FO_Row

FP_FirstCellInRow

FO_Pgf

(R3-C1)

(Footer Row)

FP_LastPgf
FP_PrevCellInRow

FP_NextCellInRow

FP_LastRowInTbl

FP_FirstPgf

FO_Cell

FO_Cell

FP_FirstPgf
FO_Pgf

(R3-C2)

FP_LastPgf
Figure 2-32 Objects that represent a table

142

FDK Programmer’s Guide

Tables

...

Frame Document Architecture

The following table lists some of the FO_Tbl object’s properties.
Property

Type

Value

FP_TblTag

StringT

Format A

FP_TblTopRuling

F_ObjHandleT

NULL

FP_TblHFSeparatorRuling

F_ObjHandleT

ID of FO_RulingFmt that
represents Double line

FP_TblBodyRowRuling

F_ObjHandleT

ID of FO_RulingFmt that
represents Thin line

FP_TblBodyFirstFill

IntT

0

FP_FirstRowInTbl

F_ObjHandleT

ID of FO_Row that represents
the heading row (row 1)

FP_LastRowInTbl

F_ObjHandleT

ID of FO_Row that represents
the footing row (row 3)

The following are some of the properties of the FO_Row object that represents the
table’s heading row.
Property

Type

Value

FP_PrevRowInTbl

F_ObjHandleT

NULL

FP_NextRowInTbl

F_ObjHandleT

ID of FO_Row that represents row 2

FP_RowType

IntT

FV_ROW_HEADING

FP_RowKeepWithNext

IntT

True

FP_FirstCellInRow

F_ObjHandleT

ID of FO_Cell that represents the R1C1 cell

FDK Programmer’s Guide 143

2

Frame Document Architecture

Tables

The following are some properties of the FO_Cell object that represents the R2-C2
cell. For the cell’s override fill and rulings to override the fill and ruling provided by the
table’s format, the FP_CellUseOverrideCharacteristic properties must be set
to True.

144

Property

Type

Value

FP_CellOverrideFill

IntT

5

FP_CellUseOverrideFill

IntT

True

FA_CellDefaultLeftRuling

F_ObjHandleT

ID of FO_RulingFmt
that represents the Medium
line ruling

FP_CellOverrideLeftRuling

F_ObjHandleT

ID of FO_RulingFmt
that represents the Thick
line ruling

FP_CellDefaultBottomRuling

F_ObjHandleT

ID of FO_RulingFmt
that represents the Medium
line ruling

FP_CellOverrideBottomRuling

F_ObjHandleT

ID of FO_RulingFmt
that represents the Thick
line ruling

FDK Programmer’s Guide

Tables

...

Frame Document Architecture

How the API represents straddle table cells
When the user straddles a set of table cells, the FrameMaker product links all of the
paragraphs in the cells. It changes the FP_FirstPgf and FP_LastPgf properties
of the first cell (topmost and leftmost) so that it specifies the first and last paragraphs of
the new linked list of paragraphs. All the other cells specify paragraph IDs of zero. It
changes the properties of the first FO_Cell object in the straddle as listed in the
following table.
Property

New value

FP_CellIsStraddled

False

FP_CellNumRowsStraddled

The number of rows in the straddle

FP_CellNumColsStraddled

The number of columns in the straddle

It also changes the properties of cells other than the first cell in the straddle as listed in
the following table.
Property

New value

FP_CellIsStraddled

True

FP_CellNumRowsStraddled

1

FP_CellNumColsStraddled

1

The straddle uses the custom rulings and shadings of the first cell. When the user
unstraddles the cells, the FrameMaker product leaves all the paragraphs that were in the
straddle in the first cell. It gives each other cell a new empty paragraph. It leaves the
original custom rulings and shadings of each cell intact.
Suppose you straddle both cells in a table row that has two cells. Each cell contains a
single paragraph before you straddle them. Figure 2-33 shows how the FO_Cell
objects appear before and after they are straddled and unstraddled. The FrameMaker

FDK Programmer’s Guide 145

2

Frame Document Architecture

Tables

product automatically inserts a new paragraph in the second cell after you unstraddle the
cells.

FO_Row

FP_FirstPgf

FP_FirstCellInRow

FO_Pgf

FO_Cell

Before straddle

FP_PrevCellInRow

FP_NextCellInRow

FP_LastPgf

FP_FirstPgf
FO_Pgf

FO_Cell
FP_LastPgf
FP_FirstPgf

FP_FirstCellInRow

FP_PrevCellInRow

After straddle

FO_Pgf

FO_Cell
FP_NextCellInRow

FO_Row

FP
_

La

stP
gf

FP_NextPgfInFlow
FP_PrevPgfInFlow

FO_Pgf
FP_FirstPgf = 0

FO_Cell
FP_LastPgf = 0

FO_Pgf

FO_Cell

FP_PrevCellInRow

After unstraddle

FP_FirstPgf

FP_FirstCellInRow

FP_NextCellInRow

FO_Row

FP
_

La

stP
gf

FP_NextPgfInFlow
FP_PrevPgfInFlow

FO_Pgf
FP_FirstPgf
FO_Pgf

FO_Cell
FP_LastPgf
Figure 2-33 Table cells before and after straddle

146

FDK Programmer’s Guide

Colors

...

Frame Document Architecture

Colors
You can assign spot colors to text and objects in a document, and you can print process
color separations. You can also set up color views to specify which colors are visible in
a document.

What the user sees
FrameMaker products provide a set of default colors. You can also define your own
colors and store them in the document’s Color Catalog. The FrameMaker product
provides three color models for creating your own colors: CMYK, RGB, and HLS. It
also provides eight color libraries; Crayon, DIC, FOCOLTONE, Greys, MUNSELL,
PANTONE® , TOYO, and TRUMATCH.

How the API represents colors
The API represents each default color and each user-defined color with an FO_Color
object. Tints are special FO_Color objects because each tint includes a reference to a
base color, which is itself an FO_Color object. For a tint, the FP_TintBaseColor
property returns the object ID of the base FO_Color object.
Paragraph formats, graphic objects, and other objects to which you can apply a color
have properties that specify the ID of an FO_Color object. For example, all graphic
objects have an FP_Color property that specifies the ID of an FO_Color object.
The properties of FO_Color objects provide the following information:


The name of the color



The color library and associated pigment used for the color



The CMYK values of the color



Tint base color and percentage



Whether the color overprints or knocks out when printing

Library colors, FP_FamilyName, and FP_InkName
When you specify a color from a library, the FP_Cyan, FP_Magenta, FP_Yellow,
and FP_Black properties are set to represent the library color. If you later set
FP_FamilyName and FP_InkName to NULL, the CMYK settings remain the same, but
the FO_Color object no longer defines a library color.
Both FP_FamilyName and FP_InkName are required to uniquely define a library
color. The order in which you set the values of these properties is important. You must
set a valid value for FP_FamilyName before you set FP_InkName. If you try to set the

FDK Programmer’s Guide 147

2

Frame Document Architecture

Colors

ink name when the family name is set to NULL, F_ApiSetString() returns an error
of FE_NoColorFamily.
When you set a value for FP_FamilyName, two things can happen:


If the current value for FP_InkName specifies a valid ink for the newly set
FP_FamilyName, then FP_InkName does not change.



If the current value for FP_InkName does not specify a valid ink for the newly set
FP_FamilyName, then the value for FP_InkName automatically changes to the
first ink name for the new color family.

If you set FP_FamilyName to a color family that is not installed on your system,
F_ApiSetString() returns an error of FE_BadFamilyName. If you set
FP_InkName to a name that is not included in the current family,
F_ApiSetString() returns an error of FE_BadInkName.
If you set one of either FP_FamilyName or FP_InkName to NULL, then the other
property value automatically changes to NULL.
Formal color library names and ink names
Note that you must specify the family name as the as the formal color library name,
including the registered trademark symbol. For example, the following sets the color
library for a color to MUNSELL® Book of Color; note the code (\xa8) for the “®”
character.
F_ApiSetString(docId, baseId, FP_FamilyName,
"MUNSELL\xa8 Book of Color");

When specifying an ink name, you don’t necessarily provide the full ink name as
described in the color library’s reference material. Some ink names have prefixes or
suffixes that are not used by the API.
The following table lists the formal name for each color library that FrameMaker
products support, along with an example of a legal string to specify an ink name via the
FDK:

148

Color library name

Ink name

Crayon

Apricot

DIC COLOR GUIDE SPOT

2298p*

FOCOLTONE

1070

Greys

49% Grey.prcs

MUNSELL® High Chrome Colors

2.5R 7:10

MUNSELL® Book of Color

2.5R 9:1

FDK Programmer’s Guide

Colors

Color library name

Ink name

PANTONE® Coated

Yellow 012

PANTONE® ProSim

Process Yellow

PANTONE® Uncoated

Yellow 012

PANTONE ProSim EURO®

Process Yellow

PANTONE® Process CSG

1-1

PANTONE® Process Euro

E 1-1

TOYO COLOR FINDER

0001pc*

TRUMATCH 4-Color Selector

1-a

...

Frame Document Architecture

Tinted colors
In FO_Color objects that are tints, the following properties have no meaning:
FP_FamilyName
FP_InkName
FP_Cyan
FP_Magenta
FP_Yellow
FP_Black

Changing these properties in a tinted color will turn the FO_Color object into an
untinted color. If you want to change the hue of a tinted FO_Color object, you must
select a new base color or change the hue of the base color.
Also, you cannot change FP_ColorPrintCtl and FP_ColorViewCtl in a tinted
color; if you try to change them, the FDK returns an error of FE_TintedColor. To
change these properties, you must change them in the tint’s base color.
FP_TintPercent
You can set FP_TintPercent to a metric value from 0.00 to 100.0 (representing
0% to 100%), or to FV_COLOR_NOT_TINTED. If you set it to
FV_COLOR_NOT_TINTED, then FP_TintBaseColor automatically changes to
FV_NO_BASE_COLOR.
When you set a percentage value for FP_TintPercent, if FP_TintBaseColor was
set to FV_NO_BASE_COLOR, then it automatically changes to the object ID for the color
Black.

FDK Programmer’s Guide 149

2

Frame Document Architecture

Structural element definitions

FP_TintBaseColor
Every tint has a base color. Note that you cannot use a tint as a base color for some other
tint. If you set the base color to FV_NO_BASE_COLOR, then the FP_TintPercent for
the current FO_Color object is set to FV_COLOR_NOT_TINTED.
When you set a valid color for FP_TintBaseColor, if FP_TintPercent was
initially set to FV_COLOR_NOT_TINTED, then it will auatomatically be set to the metric
value of 100.0 (for 100%). Be sure to change the tint percent if you want less than
100%.

Reserved colors
FrameMaker products have eight reserved colors. FO_Color objects have a read-only
property named FP_ReservedColor to specify whether the object represents a
reserved color or not. Unless the color is one of the eight reserved colors,
FP_ReservedColor will always be FV_COLOR_NOT_RESERVED.
FP_ReservedColor can have one of the following values:
FV_COLOR_NOT_RESERVED
FV_COLOR_CYAN
FV_COLOR_MAGENTA
FV_COLOR_YELLOW
FV_COLOR_BLACK
FV_COLOR_WHITE
FV_COLOR_RED
FV_COLOR_GREEN
FV_COLOR_BLUE

For a reserved color, all the properties are read-only except FP_ColorOverPrint,
FP_ColorPrintCtl,and FP_ColorViewCtl. If you try to change any of the readonly properties, the FDK returns an error of FE_ReservedColor (except for
properties that normally return FE_ReadOnly for unreserved colors).

Structural element definitions
A structured FrameMaker document has an Element Catalog, which contains structural
element definitions and named format change lists.
There are two ways to test whether a document is structured via the API. To test whether
a document contains structure elements, get the FP_HighestLevelElement property
for the main FO_Flow object in the document. To test whether the document contains
150

FDK Programmer’s Guide

Structural element definitions

...

Frame Document Architecture

an element catalog, get the FP_FirstElementDefInDoc property for the FO_Doc
object. If you get legal values for these properties, then the document contains structure
elements or an element catalog.

What the user sees
Each structural element definition has a name (tag), which usually corresponds to a type
of document component or structural element, such as Section, List, Quotation, or
BodyPara. An element definition specifies an element’s relationship to other elements
in a structured document. An element definition can also contain formatting information
about the element.
The parts of an element definition that specify an element’s format are known as the
format rules.
The part of an element definition that specifies a container element’s contents is known
as a content rule. The content rule includes the following:


A general rule, which specifies what elements are inside the container and in what
order



A list of inclusions, which specifies other elements that can appear anywhere in a
container or the elements it includes (its descendants)



A list of exclusions, which specifies elements that cannot appear in a container or in
its descendants

Element definitions also specify attribute definitions, which describe attributes or
separate units of information that the user can store with an element. An attribute
definition can specify that an attribute is required for all elements with the element
definition. It can also provide a list of the values an attribute can have, as well as a
default value.

How the API represents structural element definitions
FrameMaker represents each element definition with an FO_ElementDef object.
FO_ElementDef properties provide the following information about an element
definition:


Its name



Its format rules



Comments which describe its use



Its attribute definitions



Its content rule



The type of element it defines (for example, a container or a system variable)
FDK Programmer’s Guide 151

2

Frame Document Architecture

Structural element definitions



Flags indicating whether the element definition is defined in the Element Catalog
and whether it can be used as the highest-level element for a flow



The ID of the next FO_ElementDef object in the document



Initial structure rules for automatic insertion of child elements



Initial pattern rules for table components

The API uses an FO_FmtRule object to represent each of an element definition’s
format rules. The FO_ElementDef object has the following properties that specify an
element definition’s format rules:


FP_FirstPgfRules



FP_LastPgfRules



FP_ObjectFmtRules



FP_PrefixRules



FP_SuffixRules



FP_TextFmtRules

Each of these properties specifies an F_IntsT structure, which provides a list of
FO_FmtRule IDs.
For example, suppose you create the element definition shown in Figure 2-34.
Element type and name

Element (Container): Item
General rule: 
Text format rules
Element paragraph format: item
1. If context is: BulletList
Numbering properties
Autonumber format: \b\t
Else, if context is: NumberList
Numbering properties
Autonumber format: \t
Comment: For normal body paragraphs.

Content rule

Text format rules

Optional comment

Figure 2-34 Element definition for Item element

152

FDK Programmer’s Guide

Format rules and format rule clauses

...

Frame Document Architecture

The API represents the element definition in Figure 2-34 as an FO_ElementDef
object with the following properties:
Property

Type

Value

FP_Name

StringT

Item.

FP_ElementPgfFormat

StringT

item.

FP_NextElementDefInDoc

F_ObjHandleT

ID of the next

FO_ElementDef object in
the Element Catalog.
FP_ElementInCatalog

IntT

True.

FP_GeneralRule

StringT

.

FP_ObjectType

IntT

FV_FO_CONTAINER.

FP_Comment

StringT

For normal body
paragraphs.

FP_TextFmtRules

F_IntsT

The ID of the element
definition’s text format rule. For
a list of this format rule’s
properties, see “How the API
represents format rules and
format rule clauses” on
page 154.

Format rules and format rule clauses
An element definition can contain several format rules, each of which can contain
several format rule clauses.

What the user sees
Format rules and format rule clauses allow the template builder to specify the formats
an element has in specific circumstances. A format rule can be either a context rule or a
level rule.
A context rule contains clauses that specify an element’s formatting based on its parent
and sibling elements. For example, one clause of a format rule could specify that a Para
element has the FirstBody paragraph format if it is the first child of a Heading element.
Another clause could specify that a Para element has the Body paragraph format in all
other contexts.
A level rule contains clauses that specify an element’s formatting based on the level to
which it is nested within specific types of ancestor elements. For example, one clause of
FDK Programmer’s Guide 153

2

Frame Document Architecture

Format rules and format rule clauses

a level rule could specify that a Para element appears in 12-point type if has only one
Section element among its ancestors. Another clause could specify that a Para element
appears in 10 point type if there are two Section elements among its ancestors.
A format rule clause can use any of the following to specify an element’s formatting in
specific contexts:


A formatting tag or name, such as a paragraph tag, a character tag, or a marker name



A subformat rule



A format change list



A named format change list

How the API represents format rules and format rule clauses
The API uses an FO_FmtRule object to represent each format rule in an element
definition, and an FO_FmtRuleClause object to represent each format rule clause in
a format rule. Each FO_FmtRule object has an FP_FmtRuleClauses property,
which specifies its format rule clause.
FO_FmtRule properties provide the following information about a format rule:


A list of its format rule clauses



An indication of whether it is a context rule or a level rule



If the format rule is a level rule, the element tags to count among the element’s
ancestors and the tag at which to stop counting

FO_FmtRuleClause properties provide the following information about a format rule
clause:

154



A flag indicating how the rule clause specifies formatting, such as a paragraph tag or
a format change list



The formatting tag or name, subformat rule, or change list the rule clause uses to
specify the element’s formatting



The circumstances under which the rule clause applies: if it is in a context rule, the
context; if it is in a level rule, the level



The context label

FDK Programmer’s Guide

Format change lists

...

Frame Document Architecture

For example, the element definition shown in Figure 2-34 on page 152 includes a single
format rule. The following table lists some of the properties of that format rule.
Property

Type

Value

FP_ElementDef

F_ObjHandleT

ID of the FO_ElementDef object
that contains the format rule.

FP_FmtRuleClauses

F_IntsT

The IDs of the format rule clauses in the
format rule. For a list of the rule clause’s
properties, see the table below.

FP_FmtRuleType

IntT

FV_CONTEXT_RULE.

The F_IntsT structure specified by the FO_FmtRule object’s
FP_FmtRuleClauses property provides an array, which includes the IDs of two
format rule clauses. The following table lists some of the properties of the first format
rule clause.
Property

Type

Value

FP_ContextLabel

StringT

BulletList.

FP_FmtChangeList

F_ObjHandleT

The ID of the format change list
(FO_FmtChangeList object) that
is applied to the element when the
specified context is valid. For a list of
the change list’s properties, see “How
the API represents format change lists”
on page 156.

FP_FmtRule

F_ObjHandleT

ID of the FO_Rule object that
contains the format rule clause.

FP_RuleClauseType

IntT

FV_RC_CHANGELIST.

Format change lists
A format change list describes a set of changes to paragraph format properties.

What the user sees
A format rule clause can use format change lists to specify how a paragraph format
changes when the format rule clause applies. A change list can specify a change to just
a single paragraph property, or it can specify changes to a long list of properties.

FDK Programmer’s Guide 155

2

Frame Document Architecture

Format change lists

A change list can specify absolute values or relative values. For example, it can specify
that the paragraph left indent is one inch, or it can specify that it is one inch greater than
the inherited left indent.
A change list can be named or unnamed. A named change list appears in the Element
Catalog. Format rule clauses that use a named change list specify its name (or tag).
Multiple rule clauses can specify the same named change list. An unnamed change list
appears in a rule clause. It is used only by the rule clause in which it appears.

How the API represents format change lists
The API uses an FO_FmtChangeList object to represent each change list in a
document. FO_FmtChangeList properties provide the following information about a
change list:


Its name if it is a named change list



The ID of the next change list in the document’s list of change lists



A paragraph format tag if the change list specifies one

A change list has one property for each paragraph format property it changes. For
example, if it changes only the first indent, it has the properties described above and just
an FP_FirstIndent property. If it changes the space below and the leading, it has
the properties described above and the FP_SpaceBelow and FP_Leading
properties.
If a change list changes a paragraph property to an absolute value, the property it uses
has the same name as the corresponding paragraph format property (for example,
FP_FirstIndent). If the change list changes a property with a relative value, the
property it uses has the name of the corresponding paragraph format property with the
word Change appended to it (for example, FP_FirstIndentChange).
For example, the format rule clause in the element definition in Figure 2-34 on page 152
includes an unnamed change list. The following table lists the change list’s properties.
Property

Type

Value

FP_Name

StringT

NULL

FP_NextFmtChangeListInDoc

F_ObjHandleT

ID of the next

FO_FmtChangeList
object in the document

156

FP_PgfCatalogReference

StringT

NULL

FP_AutoNumString

StringT

\b\t

FDK Programmer’s Guide

Structural elements

...

Frame Document Architecture

Structural elements
Structured Framemaker documents contain structural elements, which are instances of
structural element definitions.

What the user sees
Each structural element is a component of a document. A structural element can consist
of one or more paragraphs, a text range, one or more child elements, or anything you can
insert in text (such as variables or tables).
Each structural element has an element definition specifying what its format and
contents should be. Elements in a document can have the same element definition. For
example, a document may have several elements with a Para element definition. For
more information on element definitions, see “Structural element definitions” on
page 150.
The elements in a container element are called its child elements. Child elements can
also be containers; container elements can be nested. The element definition’s general
rule specifies a container’s allowable child elements or text and the order in which they
should occur.
A container element can violate its content rule by omitting required child elements, by
including excluded child elements, or by having the elements in the wrong order. If a
container element obeys its content rule, it is said to be valid.
Elements can also have attributes, which correspond to XML attributes. An attribute can
be a defined attribute, which is defined in the element’s element definition, or an
undefined attribute, which is not defined in the element’s element definition.

How the API represents structural elements
FrameMaker represents a structural element with an FO_Element object, whose
properties provide the following information:


Its attributes



The ID of the object that represents its element definition



The IDs of its parent and immediate sibling elements



The IDs of the first and last FO_Element objects in the linked list of its child
FO_Element objects



Whether the element is collapsed



Whether the element is valid; and if it is invalid, the reasons it is invalid

FDK Programmer’s Guide 157

2

Frame Document Architecture

Structural elements



The ID of the object associated with the FO_Element object, if the element is a
noncontainer element, such as a marker or a system variable



The element’s context label



The format rule clauses that apply to the element

How the API represents a structural element’s validity
An element can be invalid in several ways. For example, its parent’s content rule may
not allow it, or it may contain a child element that is not allowed. FO_Element objects
have validation properties that indicate the extent of an element’s validity. For example,
an element has a property named FP_ElementIsInvalidInParent, which is set to
True if the element is not allowed by its parent element.

Changing an element
When using FrameMaker, an author can select elements and wrap, merge, or change
them. The API provides functions to wrap and merge elements directly; for example,
F_ApiMergeIntoFirst(). However, there is no corresponding function to directly
change an element. Changing an element corresponds to a user selecting an element in
the document, selecting an element name in the Element catalog, and then clicking
Change on the element catalog.
To change an element via the API, you must change the FP_ElementDef property of
the FO_Element object. You can traverse the list of element definitions in the
document by starting with the FP_FirstElementDefInDoc property of the FO_Doc
object, and then using the FP_NextElementDefInDoc property of the resulting
FO_ElementDef object. You can identify the element definition by using its FP_Name
property.

158

FDK Programmer’s Guide

3

Frame Book Architecture

..................................
.....

3

This chapter describes books and discusses how the Frame API represents them.

What the user sees
A book maintains a collection of documents that are known as components. The book
helps you organize and format these component documents. It also enables you to create
generated files, such as tables of contents and indexes. A book does not contain the
component document files. It contains references to the component document files, in
an ordered list; such a reference is called a book component.
Each component contains its own setup data such as pagination and numbering. For
example, each component contains properties to determine whether its page and
paragraph numbering continues from the previous document or restarts at 1, and
whether the document starts on a left or right page.
The component properties should not differ from the corresponding properties in the
document file. However, by setting the values in one but not both, a client could set up
a component with different numbering properties than the corresponding document file.
Subsequent book updates will make the numbering properties match.
For example, the paragraph numbering for a set of document in files might be set to
restart at 1. When the user adds the documents to the book, then each component will
have the same numbering properties. Your client could loop through a book and set the
numbering for each component to continue from the previous file. In this case, when
your client (or the user) updates the book, the FrameMaker product will change the
numbering for the document files so they match the component numbering. For more
information about how component and document numbering properties interact, see
your Frame product user’s manual.

FDK Programmer’s Guide 159

3

Frame Book Architecture

How the API represents books

..............................................................................

IMPORTANT: A book component can be a document saved in any file format. The FDK
can only modify document objects in documents that were saved in FrameMaker binary
(FASL) files, but you can use channels to open MIF or text files and modify them.
..............................................................................

How the API represents books
The API represents each book with an FO_Book object which can contain one or more
FO_BookComponent objects.
FO_Book objects have properties that provide the following information:


Whether the book has been modified



Display properties such as book window size and location, text to show for each
component, and text in the book’s status line



Whether or not the book is view-only, and view-only display properties



Selection state; whether the book icon is selected, the first selected component, or the
range of selected structure elements in the book



Properties that determine how to print the book and save it as PDF



For structured books, structure properties such as the element catalog for the book
and the ID of the highest level element in the book

An FO_BookComponent object represents an individual book component. It has
properties that provide the following information:

160



The name of the document represented by the component



The IDs of the next and previous component in the book and the next selected
component in the book



Whether the component is generated, and the type of generated file; in other words,
whether the component is a specific type of list or index



Whether to include the component in print, update, and import formats operations



The list of paragraph format tags the product uses to generate a list from this
component



The ID of the parent book



Numbering and pagination properties for the component; these properties may differ
from the document’s specific set of numbering properties



For structured books, the structural element representing the book component

FDK Programmer’s Guide

How the API represents books

...

Frame Book Architecture

Suppose you create the book in Figure 3-1. The book is named
C:\MyDocs\book1.book, and has three documents; myDoc1.fm, myDoc2.fm, and
myDoc3.fm.

Figure 3-1 A book with three components

The API represents mybook.book with one FO_Book object and three
FO_BookComponent objects. The following table lists some of the FO_Book
object’s properties.
Property

Type

Value

FP_Name

StringT

C:\MyDocs\book1.book

FP_NextOpenBookInSession

F_ObjHandleT

0

FP_FirstComponentInBook

F_ObjHandleT

ID of FO_BookComponent
object for myDoc1.fm

FP_FirstSelectedComponent
InBook

F_ObjHandleT

ID of FO_BookComponent
object for myDoc3.fm

FP_StatusLine

StringT

Empty string (""); the status
line currently displays no text

FP_TypeOfDisplayText

IntT

FV_BK_FILENAME

The following code shows how to get properties from the selected book component.
First it gets the active book, and then the first selected component in the active book. For
the book in Figure 3-1, the component would be for myDoc3.fm. For the selected
component, the code prints out the method the component uses to compute footnote
numbering. Then, if the footnote numbering uses custom characters for footnotes
(daggers, etc.), the code prints out the custom numbering string.

FDK Programmer’s Guide 161

3

Frame Book Architecture

How the API represents books

VoidT F_ApiCommand(command)
IntT command;
{
F_ObjHandleT bookId, compId;
StringT numString;
bookId = F_ApiGetId(0,FV_SessionId, FP_ActiveBook);
compId = F_ApiGetId(FV_SessionId, bookId,
FP_FirstSelectedComponentInBook);
F_Printf(NULL, "\n CompName is: %s",
F_ApiGetString(bookId, compId, FP_Name));
switch(F_ApiGetInt(bookId, compId, FP_FnNumComputeMethod)) {
case FV_NUM_RESTART:
F_Printf(NULL, "\nFn Compute: FV_NUM_RESTART");
break;
case FV_NUM_CONTINUE:
F_Printf(NULL, "\nFn Compute: FV_NUM_CONTINUE");
break;
case FV_NUM_PERPAGE:
F_Printf(NULL, "\nFn Compute: FV_NUM_PERPAGE");
break;
case FV_NUM_READ_FROM_FILE:
F_Printf(NULL,"\nFN Compute: FV_NUM_READ_FROM_FILE");
break;
default:
F_Printf(NULL, "\nFn Num Compute Method: UNKNOWN");
break;
}
if(F_ApiGetInt(bookId, compId, FP_FnNumStyle)
== FV_FN_NUM_CUSTOM) {
F_Printf(NULL, "\nFn Num Style: FV_FN_NUM_CUSTOM");
numString = F_ApiGetString(
bookId, compId, FP_FnCustNumString);
F_Printf(NULL, "\n
Cust Str: %s", numString);
F_ApiDeallocateString(&numString);
}
}

162

FDK Programmer’s Guide

How the API represents books

...

Frame Book Architecture

How the API organizes book components
The API organizes the FO_BookComponent objects that represent
a book’s components in a linked list. The FO_Book object’s
FP_FirstComponentInBook property specifies the first FO_BookComponent
object in the list. Each FO_BookComponent object has
FP_PrevComponentInBook and FP_NextComponentInBook properties
that specify the IDs of the previous and next FO_BookComponent objects in the list.
The order of the list is the same as the order of the components in the book.
Suppose you create the book shown in Figure 3-1 on page page 161. The API represents
this book with the objects shown in Figure 3-2.
FP_FirstComponent
InBook
FO_Book

FO_Book
Component

myDoc1.fm

FO_Book
Component

myDoc2.fm

FP_NextComponentInBook

FP_PrevComponentInBook

FO_Book
Component

myDoc3.fm

Figure 3-2 Objects that represent a book and its components

How the API represents structured books
If a book is a FrameMaker structured book, it has an FP_HighestLevelElement
property, which specifies the ID of the FO_Element object that represents the root
element. Each component in the book also has an FP_ComponentElement property,
which specifies the FO_Element object ID for that component’s structure element.

FDK Programmer’s Guide 163

3

Frame Book Architecture

Creating new books and components

Creating new books and components
To create a new book, use F_ApiNewNamedObject(). If you pass an empty string for
the object name, the FrameMaker product creates an untitled book.
To insert a new book component in a book, use F_ApiNewSeriesObject(). This
creates a new book component, but the component has no document file assigned to it.
If the user tries to to open such a component’s file, the FrameMaker product will alert
the user that no file exists to match the component name. When you insert a new book
component, you should assign a document to it.
For more information on F_ApiNewSeriesObject(), see “Creating series objects”
on page 365.
The following code creates an untitled book with one component that represents a newly
created, custom document file. After the code successfully saves the new document, it
creates a book component and assigns the document name to the new component.
#define in ((MetricT) 65536*72)
. . .
VoidT F_ApiCommand(command)
IntT command;
{
F_ObjHandleT bookId, docId, compId;
StringT s;
F_ApiBailOut();
bookId = F_ApiNewNamedObject(FV_SessionId,
FO_Book, (StringT)"");
/* First create an 8.5 x 11 custom document. */
docId = F_ApiCustomDoc(F_MetricFractMul(in,17,2), 11*in, 1,
F_MetricFractMul(in,1,4), in, in, in, in,
FF_Custom_SingleSided, True);
/* Save the doc, prompting for filename */
F_ApiSimpleSave(docId, (StringT)"", True);
/* If file has name, make a component */
s = F_ApiGetString(FV_SessionId, docId, FP_Name);
if(F_StrLen(s)) {
compId = F_ApiNewSeriesObject(
bookId, FO_BookComponent, 0);
F_ApiSetString(bookId, compId, FP_Name, s);
F_ApiDeallocateString(&s);
}
}

164

FDK Programmer’s Guide

Updating a book

...

Frame Book Architecture

Updating a book
After making changes in the documents or components of a book, your client must
update the book to ensure all references are valid. For example, if you change the page
numbering properties, you must update the book to ensure cross-references indicate the
correct numbering. You can update a book via the F_ApiUpdateBook() command or
the F_ApiSimpleGenerate() command.
With F_ApiUpdateBook(), you can specify aspects of the Update operation, such as
whether to update books with view-only documents. You can specify all aspects of the
operation, or you can specify some aspects and allow the user to decide others. For
example, you can instruct the FrameMaker product to post an alert if the book contains
a MIF file.
To use F_ApiUpdateBook(), you should first understand property lists and how to
manipulate them directly. For more information on this subject, see “Representing
object characteristics with properties” on page 63 and “Manipulating property lists
directly” on page 293.
The syntax for F_ApiUpdateBook() is:
ErrorT F_ApiUpdateBook(F_ObjHandleT bookId,
F_PropValsT *updateParamsp,
F_PropValsT **updateReturnParamspp);
This argument

Means

docId

The ID of the document or book to save.

updateParamsp

A property list that tells the FrameMaker product how to update
the book and how to respond to errors and other conditions. Use
F_ApiGetUpdateBookDefaultParams() or
F_ApiAllocatePropVals() to create and allocate memory
for this property list. To use the default list, specify NULL.

updateReturn
Paramspp

A property list that returns information about how the
FrameMaker product updated the book.

..............................................................................

IMPORTANT: Always initialize the pointer to the property list that you specify for
updateReturnParamspp to NULL before you call F_ApiUpdateBook().
..............................................................................

To call F_ApiUpdateBook(), do the following:
1 Initialize the pointer to the updateReturnParamspp property list to NULL.

FDK Programmer’s Guide 165

3

Frame Book Architecture

Updating a book

2 Create an updateParamsp property list.
You can get a default list by calling F_ApiGetUpdateBookDefaultParams(), or
you can create a list from scratch.
3 Call F_ApiUpdateBook().
4 Check the Update status.
Check the returned values in the updateReturnParamspp list for information about
how the FrameMaker product updated the book.
5 Deallocate the updateParamsp and updateReturnParamspp property lists.
Steps 2, 4, and 5 are discussed in the following sections.

Creating an updateParamsp script with
F_ApiGetUpdateBookDefaultParams()
The API provides a function named F_ApiGetUpdateBookDefaultParams()
that creates a default updateParamsp property list. If you are setting a number of
properties, it is easiest to use this function get the default property list and then change
individual properties as needed.
The syntax for F_ApiGetUpdateBookDefaultParams() is:
F_PropValsT F_ApiGetUpdateBookDefaultParams();

The following table lists some of the properties in the property list returned by
F_ApiGetUpdateBookDefaultParams(). The first value listed for each property
is the default value for the property. You can change any property in the list to use its
other legal values.
Property

Meaning and possible values

FS_AlertUserAboutFailure

Specifies whether to notify the user if something unusual
occurs during the update operation
False: don’t notify user
True: notify user

FS_MakeVisible

Make newly generated files (lists and indexes) visible
True: make visible
False: don’t make visible

166

FDK Programmer’s Guide

Updating a book

...

Frame Book Architecture

Property

Meaning and possible values

FS_ShowBookErrorLog

Specifies whether to use the book error log to display
warnings.
False: don’t display book error log; display warnings in
the console
True: display the book error log

For the complete list returned by F_ApiGetUpdateBookDefaultParams(), see
“F_ApiGetUpdateBookDefaultParams()” on page 271 of the FDK Programmer’s
Reference.
For example, to get a default updateParamsp property list and modify it so that it
instructs F_ApiUpdate() to show the book error log, use the following code:
. . .
F_PropValsT params;
ErrorT err;
. . .
/* Get the default parameter list. */
params = F_ApiGetUpdateBookDefaultParams();
/* Get the index for the error log property, */
/* then set the property to True. */
i = F_ApiGetPropIndex(¶ms, FS_ShowBookErrorLog);
params.val[i].propVal.u.ival = True;
. . .

The API allocates memory for the property list created by
F_ApiGetUpdateBookDefaultParams(). Use
F_ApiDeallocatePropVals() to free the property list when you are done with it.

Creating an updateParamsp script from scratch
If you want to specify only a few properties when you call F_ApiUpdateBook(), it
is most efficient to create a property list from scratch. To create the property list, you
must allocate memory for it, and then set up the individual properties.
Use the API convenience function, F_ApiAllocatePropVals(), to allocate
memory for the property list. For example, the following code creates an

FDK Programmer’s Guide 167

3

Frame Book Architecture

Updating a book

updateParamsp property list that will instruct F_ApiUpdateBook() to display the
error log:
#DEFINE ERR_LOG 0
. . .
F_PropValsT params, *returnParamsp = NULL;
. . .
/* Allocate memory for the list. */
params = F_ApiAllocatePropVals(1);
/* Set up FS_ShowBookErrorLog property and set it to True. */
params.val[ERR_LOG].propIdent.num = FS_ShowBookErrorLog;
params.val[ERR_LOG].propVal.valType = FT_Integer;
params.val[ERR_LOG].propVal.u.ival = True;
. . .
/* When you’re finished, free the F_PropValsT */
F_ApiDeallocatePropVals(¶ms)

Checking update status
F_ApiUpdateBook() stores a pointer to a property list in
updateReturnParamspp; the list contains one property which contains flags to
indicate the status. For a list of the possible flags, see “F_ApiUpdateBook()” on
page 473 of the FDK Programmer’s Reference.
To determine if a particular FS_UpdateBookStatus bit is set, use
F_ApiCheckStatus(). For example, the following code determines if an Update
operation was canceled because the current book contains duplicate files (components
that refer to the same file):

168

FDK Programmer’s Guide

Updating a book

...

Frame Book Architecture

. . .
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT bookId;
/* Get the ID of the active book. */
bookId = F_ApiGetId(0, FV_SessionId, FP_ActiveBook);
params = F_ApiGetUpdateBookDefaultParams();
F_ApiUpdate(bookId, ¶ms, &returnParamsp);
if (F_ApiCheckStatus(returnParamsp, FV_DuplicateFileInBook))
F_ApiAlert("Duplicate files in book.",
FF_ALERT_CONTINUE_NOTE);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API provides a utility function named F_ApiPrintUpdateStatus(), which
prints the save error values to the console platforms. For more information, see
“F_ApiPrintUpdateBookStatus()” on page 369 of the FDK Programmer’s Reference.

FDK Programmer’s Guide 169

3

Frame Book Architecture

Using the book error log

Example
The following code updates the currently active book. The update operation will display
the error log for any error conditions, will allow inconsistent numbering properties, and
(since the code allows inconsistent numbering) will not update the numbering in the
book. It then prints out the update status. Finally, the code deallocates the property lists
that it used to update the book.
. . .
#include "futils.h"

IntT i;
UCharT msg[1024];
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT bookId;

params = F_ApiGetUpdateBookDefaultParams();
i = F_ApiGetPropIndex(¶ms, FS_ShowBookErrorLog);
params.val[i].propVal.u.ival = True;
i = F_ApiGetPropIndex(¶ms, FS_AllowInconsistentNumProps);
params.val[i].propVal.u.ival = FV_DoOk;
i = F_ApiGetPropIndex(¶ms, FS_UpdateBookNumbering);
params.val[i].propVal.u.ival = False;

err = F_ApiUpdateBook(bookId, ¶ms, &returnp);
F_ApiPrintUpdateBookStatus(returnp);

F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnp);

. . .

Using the book error log
When updating a book, the FrameMaker product posts errors to a book error log. The
error log is a FrameMaker document that lists error conditions and includes hypertext
links to offending locations in the book’s document files.
By default, FDK clients post book errors to the console. However, your clients can post
errors to the log, and can include hypertext links in those messages.

170

FDK Programmer’s Guide

Using the book error log

...

Frame Book Architecture

Displaying the error log for book updates
By default, the FrameMaker product displays update errors in the console. You direct
the FrameMaker product to display the error log via the property list you pass to
F_ApiUpdateBook(). In that list, set the FS_ShowBookErrorLog flag to True. For
more information about the update book properties, see “Creating an updateParamsp
script with F_ApiGetUpdateBookDefaultParams()” on page 166.

Writing messages to the error log
The FrameMaker product includes an API client that writes messages to the error log.
To write a message to the error log, you must use F_ApiCallClient().
The syntax for the client call is:
F_ApiCallClient("BookErrorLog",
"log -b=[bookId] -d=[docId] -o=[objId] --[text]");

where:


BookErrorLog is the name of the client to call.



log identifies this as a log message.



-b is either the book ID or a document ID; typically the active book.



-d is either a document ID or an object ID; typically a document associated with a
book component.



-o is an object in the document represented by the -d argument. If you pass both a
document ID and an object ID, the call adds a hypertext link, from the error message
to the object you specified.



-- is the text of the message to appear in the log. To post a time stamp in the
message, pass the FM_PRINT_DATESTAMP token as the message string.

The call creates a unique log for each book or document ID you pass in the -b
argument; if you pass 0 for a book ID, you will create a log that is not associated with
any book; all calls with the 0 book ID will go to that log file.
When you pass a document ID for the -d argument, the call creates an entry with the
document’s pathname. It then indents all contiguous entries with the same document ID
under that document’s pathname. This continues until you pass a different document ID.
If you pass 0 for the -d argument, the call will not indent the errors.
If you don’t have the document ID, you can specify log entry indenting under a filename
via the text you pass for the log message. To do this, you precede the log message with
a filename, followed by a carriage return. This method creates an indented section each
time you pass a filename and carraige return, even if you pass the same filename in a
series of log entries.

FDK Programmer’s Guide 171

3

Frame Book Architecture

Using the book error log

For example, if you passed the following to the BookErrorLog client in two consecutive
calls:
"filename.fm\012Here is my first Log Message"
"filename.fm\012Here is my second Log Message"
The BookErrorLog client would create the following messages:
filename.fm
Here is my first Log Message
filename.fm
Here is my second Log Message

Example
The following code shows a function that posts messages to a log, with or without a time
stamp; if you pass valid ID’s for all the ID arguments, the log message will include a
hypertext link to the specified object in the specified document:
VoidT ReportError(F_ObjHandleT docId, F_ObjHandleT objId,
ConStringT errmsg, BoolT dateStamp)
{
F_ObjHandleT bookId;
StringT log_msg = F_StrNew((UIntT)256);
bookId = F_ApiGetId(0, FV_SessionId, FP_ActiveBook);
if(dateStamp) {
F_Sprintf(log_msg, "log -b=%d -d=%d -o=%d --%s",
bookId, docId, objId, (StringT)"FM_PRINT_DATESTAMP");
} else {
F_Sprintf(log_msg, "log -b=%d -d=%d -o=%d --%s",
bookId, docId, objId, errmsg);
}
F_ApiCallClient("BookErrorLog", log_msg);
F_ApiDeallocateString(&log_msg);
}

172

FDK Programmer’s Guide

PART III

..........................................

Frame Application Program Interface

4

Introduction to the Frame API

..................................
.....

1

This chapter provides an overview of how the API works and how to create an FDK
client. It also provides a simple example—a client that you can create and run right
away.
The API enables you to create a client that takes control of a FrameMaker product
session. With the API, a client can do almost anything an interactive user can do. It can
create, save, and print documents; add and delete text and graphics; and perform many
other formatting and document-management tasks. It can also interact with the user by
responding to user actions, displaying dialog boxes, and creating menus.

How the API works
The API represents everything in a FrameMaker product session as an object.1 Each
object has a type, a constant that indicates the type of thing it represents. For example,
an object’s type can be FO_Doc (if it represents a document), FO_Rectangle (if it
represents a graphic rectangle), or FO_Pgf (if it represents a paragraph).
FrameMaker products assign an identifier (ID) to each object in a session. You use this
ID to identify an object when you call API functions.
An object’s characteristics are called properties. Each type of object
has a particular set of properties or a property list. For example, an FO_Rectangle
object’s property list includes properties named FP_Width and FP_Height, which
represent its height and width. An FO_Pgf object’s property list includes properties
named FP_LeftIndent and FP_Leading, which represent its left indent and its
leading. Each property has a predetermined data type, such as IntT (integer, Boolean,
or ordinal), StringT (string), or F_ObjHandleT (object ID).
Each of an individual object’s properties has a value. This value describes the property
for that particular object. For example, suppose a document contains a smoothed

.................................
1. Frame API objects should not be confused with the graphic objects that you create with the Tools palette,
object elements in structured documents, or the objects of object-oriented programming languages.

FDK Programmer’s Guide 175

4

Introduction to the Frame API

How the API works

rectangle that is 20 points wide and 10 points high. The Frame API represents the
rectangle as an FO_Rectangle object with the following properties and values.
Property

Data Type

Value

FP_Width

MetricT

20 * 65536a

FP_Height

MetricT

10 * 65536

FP_RectangleIsSmoothed

IntT

True

FP_FrameParent

F_ObjHandleT

ID of the frame containing the
rectangle

a. MetricT values are 32-bit integers that represent measurements in points. The 16 most significant bits
represent the digits before the decimal. The 16 least significant bits represent the digits after the decimal.
A point is 65536 (1 << 16) in MetricT units. For more information on MetricT, see “MetricT values”
on page 950 of the FDK Programmer’s Reference.

FO_Rectangle objects actually have many more properties than are shown in the
table above. For a complete list of Frame API objects and properties, see Chapter 3,
“Object Reference,” of the FDK Programmer’s Reference.

How clients can change FrameMaker product documents, books, and
sessions
A client can change FrameMaker documents, books, and sessions by:


Creating and destroying objects
The API provides functions to create and destroy objects.



Changing object properties
The API provides functions to get and set object properties.



176

FDK Programmer’s Guide

Programmatically executing FrameMaker product commands, such as Open, Print,
Save, and Clear All Change Bars

Special types of clients

...

Introduction to the Frame API

How clients communicate with the user
A client can communicate with the user by:


Creating menus and menu items



Displaying dialog boxes

The API allows a client to respond to user actions by:


Notifying the client when the user initiates certain events, such as Open, Save, or
Quit



Passing a message to the client when the user clicks a hypertext marker that contains
a message apiclient hypertext command

How clients work with FrameMaker
Clients are dynamic link libraries (DLLs), or they can be executable programs that use
COM to communicate with a FrameMaker session.. A client does not need to be aware
of the low-level details of integrating with FrameMaker, because the API provides
high-level functions that are the same on all platforms.
When the user starts FrameMaker, it sends an initialization call to each registered client.
Clients can take control immediately, or they can request FrameMaker to notify them of
specific events and wait for those events to occur.

Special types of clients
In addition to conventional clients that take control of a FrameMaker product session in
response to user actions, the API allows you to create three special types of clients:
document reports, filters, and take-control clients.

Document reports
A document report is a client that provides detailed information about a document. The
user can start a document report by choosing Utilities>Document Reports from the File
menu, and then choosing the report from the Document Reports dialog box. The FDK
includes a sample document report, named wordcnt, which counts the number of
words in a document.

Filters
A filter is a client that converts FrameMaker product files to or from other file formats.
An import filter is a filter that the FrameMaker product calls when the user attempts to
open a non-Frame file and chooses a filter in the Unknown File Type dialog box. The
FDK Programmer’s Guide 177

4

Introduction to the Frame API

Special types of clients

import filter reads the file and converts it to a FrameMaker product document or book.
The FDK includes a sample import filter, named mmlimport, that converts MML files
to FrameMaker product documents.
An export filter is a filter that the FrameMaker product calls when the user attempts to
save a FrameMaker product document or book in a particular format by choosing the
format in the Save dialog box or by specifying a filename with a particular extension.
The export filter writes information in the document or book to a file with a different
format.
A file-to-file filter is a filter that the FrameMaker product can call to both import or
export files of different formats. A single file-to-file filter client can actually consist of
more than one filter. For example, the same client could filter CGM to FrameVector and
FrameVector to CGM. The way you register the client’s different filters determines
which filter to invoke for import and export. Another advanage of these filters is they
can filter from an external file to an external file. For example, you could filter from
CGM to TIFF, and the TIFF file can remain an external file that is imported into the
document by reference.

Take-control clients
A take-control client is a client that takes control of a FrameMaker product session
immediately after the FrameMaker product starts. Take-control clients are useful for
conducting batch operations in which little or no user interaction is needed.

Portability
The API’s design makes it easy to create portable clients. In most cases, you only need
to recompile your client to run it on a different platform. To ensure that your client is
completely portable, use the FDE with the API. You should replace platform-specific
I/O, string, and memory functions in your client with the alternatives the FDE provides.
For more information on the FDE, see Part III, “Frame Development Environment
(FDE).”
The FDE and the API provide alternatives to the C language’s fundamental data types.
For example, the FDE and the API substitute IntT for a 32-bit int and UCharT
for unsigned char. The API uses other types for specific purposes. For example, it
uses F_ObjHandleT for object IDs. For a list of API data types, see Chapter 4, “Data
Types and Structures Reference,” of the FDK Programmer’s Reference.

178

FDK Programmer’s Guide

Running clients with different FrameMaker product interfaces

...

Introduction to the Frame API

Running clients with different FrameMaker product interfaces
FrameMaker ships with two product interfaces, Structured FrameMaker and
FrameMaker. A client can only use functionality that is available in the product
interface that is active for the currently running FrameMaker process. For example, if a
client is running on the unstructured FrameMaker product interface, it can’t create or
manipulate structural elements (FO_Element objects). On the other hand, all
functions in the FDK are available to a client running on the Structured FrameMaker
product interface.
To determine if a function is available in a particular product interface, see Chapter 2,
“FDK Function Reference,” of the FDK Programmer’s Reference. For an example of
how to programmatically determine which product interface is running, see
“F_ApiGetString()” on page 234 of the FDK Programmer’s Reference.

Creating and running a client
To create and run a client, follow these general steps:
1 Write an initialization function.
Most clients need to define an F_ApiInitialize() callback function. When the
FrameMaker product starts, it calls your client’s F_ApiInitialize() function.
Normally, you will want to include code in F_ApiInitialize() to set up your
client’s menus and request notification for particular events.
For more information on creating an F_ApiInitialize() callback, see Chapter 2,
“API Client Initialization.”
2 Set up the client’s user interface.
Your client probably needs to interact with the user. To respond to user actions, you can
define the following callback functions in your client:


F_ApiNotify() to respond to the user initiating FrameMaker product operations,
such as Open and Save



F_ApiCommand() to respond to the user choosing menu items created by your
client



F_ApiMessage() to respond to the user clicking hypertext markers that contain
the message apiclient command



F_ApiDialogEvent() to respond to the user manipulating items in a dialog box
created by your client

You can also display notices and prompt the user for input by using API dialog box
functions, such as F_ApiAlert() and F_ApiPromptString().

FDK Programmer’s Guide 179

4

Introduction to the Frame API

Creating and running a client

For more information on setting up your client’s user interface, see Chapter 3, “Creating
Your Client’s User Interface.”
3 Add code to programmatically execute FrameMaker product commands.
Your client probably needs to execute some FrameMaker product commands, such as
Open, Print, or Close. To execute these commands programmatically, use API
functions, such as F_ApiSimpleOpen(), F_ApiSilentPrintDoc(), or
F_ApiClose().
For more information on using API functions to execute FrameMaker product
commands, see Chapter 4, “Executing Commands with API Functions.”
4 Add code to get and set object properties.
To get or set an object property, use the F_ApiGetPropertyType() or
F_ApiSetPropertyType() function that corresponds to the type of property you
want to get or set. For example, to get or set an IntT property, use F_ApiGetInt()
or F_ApiSetInt(). To get or set a StringT property, use F_ApiGetString()
or F_ApiSetString().
For more information on changing object properties, see Chapter 5, “Getting and
Setting Properties.”
5 Add code to create objects.
To create objects, use the F_ApiNewObjectType() function that corresponds to the
kind of object that you want to create. For example, to create a new anchored frame, use
F_ApiNewAnchoredObject().
For more information on creating objects, see Chapter 8, “Creating and Deleting API
Objects.”
6 Compile your client.
The API function declarations are contained in the fapi.h header. Be sure to include
this header in your client code. Include C library header files before the fapi.h
header.
The FDK comes with sample makefiles or project files for each supported platform. To
compile your client, use your platform’s make or build utility. For more information on
using FDK makefiles or project files on a specific platform, see the FDK Platform
Guide for that platform.
7 Register your client with the FrameMaker product.
The FrameMaker product needs to know about your client to initialize it. To let the
FrameMaker product know about your client, you must make some changes to the
environment under which the client runs.


Add the following lines to the [APIClients] section of the maker.ini file:
ClientName=ClientType, description, path, mode

ClientName is the name that the FrameMaker product and other clients use to
reference your client. ClientType specifies your client type: for example,
180

FDK Programmer’s Guide

A simple example

...

Introduction to the Frame API

Standard, DocReport, or TextImport. description is a string describing
your client. path is the pathname of your client’s DLL. mode determines what
product interfaces your client supports—can be one of all, maker, or
structured.
You can also register a Windows client by setting values in the DLL’s
VERSIONINFO resource, then copying or moving the DLL in the PrameMaker
product’s Plugins folder..

A simple example
The following client adds a menu with three items to the FrameMaker product menu bar
when the FrameMaker product starts. The first menu item closes the active document;
the second item sets the fill pattern of a selected graphic object; the third item adds a
body page to the active document. Following the code is a line-by-line description of
how it works.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#include "fapi.h"
#define CloseDoc 1
#define SetFill 2
#define AddPage 3
VoidT F_ApiInitialize(initialization)
IntT initialization;
/* Code for initialization type */
{
F_ObjHandleT menuBarId, menuId;
/* Get ID of the FrameMaker product menu bar. */
menuBarId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"!MakerMainMenu");
/* Add menu named "API" to the FrameMaker product menu bar. */
menuId = F_ApiDefineAndAddMenu(menuBarId, "APIMenu", "API");
/* Add items to API menu. */
F_ApiDefineAndAddCommand(CloseDoc, menuId,"CloseDocCmd",
"Close","\\!CD");
F_ApiDefineAndAddCommand(SetFill, menuId,"SetFillCmd",
"Set Fill","\\!SF");
F_ApiDefineAndAddCommand(AddPage, menuId,"AddPageCmd",
"Add Page","\\!AP");
}
VoidT F_ApiCommand(command)
IntT command;
{
F_ObjHandleT pgId, objId, docId;

FDK Programmer’s Guide 181

Introduction to the Frame API

4

A simple example

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

/* Get the ID of the active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if(!docId) return; /* Return if there is no active document. */
switch (command)
{
case CloseDoc:
/* Close document even if it’s changed. */
F_ApiClose(docId, FF_CLOSE_MODIFIED);
break;
case SetFill:
/* Set fill pattern to black. */
/* Get ID of selected object. */
objId = F_ApiGetId(FV_SessionId, docId,
FP_FirstSelectedGraphicInDoc);
/* If an object is selected, set its fill. */
if (!objId) F_ApiAlert("Select an object first.",
FF_ALERT_CONTINUE_WARN);
else F_ApiSetInt(docId, objId, FP_Fill, FV_FILL_BLACK);
break;
case AddPage:
/* Add a new page. */
pgId = F_ApiNewSeriesObject(docId, FO_BodyPage, 0);
break;
}
}

Lines 1–5
These lines include header files and define the constants for the client’s menu items. All
clients must include the fapi.h header. To ensure your client is portable, include
fapi.h before any other header files.
Lines 6–25
These lines define the F_ApiInitialize() callback function. When the user starts
the FrameMaker product, it calls F_ApiInitialize().
The call to F_ApiGetNamedObject() gets the ID of the FrameMaker product menu
bar (!MakerMainMenu). The call to F_ApiDefineAndAddMenu() creates a menu
named API on the menu bar. The calls to F_ApiDefineAndAddCommand() add
menu items to the API menu and define keyboard shortcuts for the items.
Lines 26–56
These lines define the F_ApiCommand() callback function. When the user chooses a
menu item, the FrameMaker product calls this callback with command set to the menu
item number (in this example, CloseDoc, SetFill, or AddPage).

182

FDK Programmer’s Guide

A simple example

...

Introduction to the Frame API

Lines 31–34
These lines get the ID of the document to change. To use most API functions, you need
to specify an ID. This example gets the ID of the document that has input focus, that is,
the active document.
In each FrameMaker product session there is only one active document at a time. The
session object (FO_Session) has a property named FP_ActiveDoc that specifies its
ID. To retrieve the active document’s ID from the FO_Session object, you use
F_ApiGetId() to query the FO_Session object’s FP_ActiveDoc property. The
syntax for F_ApiGetId() is:
F_ObjHandleT F_ApiGetId(parentId, /* Object’s parent */
objId, /* Object whose property you want to query */
property);/* Constant specifying property to query */

The parentId parameter specifies the ID of the object’s parent—the session, book,
or document that contains the object. No other object contains the FO_Session
object, so parentId is set to 0. The ID of the FO_Session object (there can only
be one) is always FV_SessionId, so objId is set to FV_SessionId.
Lines 37–40
These lines close the active document when the user chooses Close Doc from the API
menu. The FF_CLOSE_MODIFIED flag instructs the API to close the document
without warning the user, even if the document has unsaved changes.
Lines 41–51
These lines set the fill pattern of a selected object to black when the user chooses Set Fill
from the API menu. To set the selected object’s fill pattern, the client needs the object’s
ID. To get the ID, the client uses F_ApiGetId() to query the document property,
FP_FirstSelectedGraphicInDoc. If no object is selected, F_ApiGetId()
returns 0.
The F_ApiAlert() call displays an alert that tells the user to select an object. The
constant, FF_ALERT_CONTINUE_WARN, specifies the type of alert—an alert with a
Continue button.

FDK Programmer’s Guide 183

4

Introduction to the Frame API

A simple example

To set the object’s fill pattern, the client must set its FP_Fill property. FP_Fill is
an IntT property, so the client must use F_ApiSetInt() to set it. The syntax for
F_ApiSetInt() is:
VoidT F_ApiSetInt(parentId,/* Object’s parent */
objId, /* Object whose property you want to set */
property, /* Constant specifying property to set */
value);/* Value to which to set the property */

FP_Fill can have any value between 0 and 15. The API-defined constant,
FV_FILL_BLACK, specifies 0 (black).
Lines 52–54
These lines add a body page to the document when the user chooses
Add a Page from the API menu. A body page object is a series object. To create a series
object, you use F_ApiNewSeriesObject(). The syntax for
F_ApiNewSeriesObject() is:
F_ObjHandleT F_ApiNewSeriesObject(parentId,/* Object’s Parent */
objectType, /* Constant specifying new object type */
prevObjectId); /* Object for new object to follow */

The parentId parameter specifies the ID of the object that is to contain
the new object. The new page should appear in the active document, so parentId is
set to docId. The API uses FO_BodyPage objects to represent body pages, so
objectType is set to FO_BodyPage. Specifying 0 for prevObjectId puts the
new page at the beginning of the document. For more information on creating different
types of objects, see “Creating objects” on page 357.

184

FDK Programmer’s Guide

Using old clients with FDK 12

...

Introduction to the Frame API

Compiling and running the example client
The source code for the example client and a makefile or project file are provided in
provided in the samples/myapi directory of your FDK installation.
To compile the client, use your platform’s make or build utility.
To run the example client, you must first register it. Assuming you have compiled
your client into a DLL named myapi.dll and copied or moved it to the FrameMaker
fminit directory, add the following line to the maker.ini file:
myapi = Standard,Ch. 1 Sample,fminit\myapi.dll

After you have registered the example client, start FrameMaker and open a document.
The API menu should appear to the right of the FrameMaker menus.

Using old clients with FDK 12
For legacy clients compiled with FDK 10 to run successfully with FDK 12, they should
be recompiled with Microsoft Visual Studio 2010.

FDK Programmer’s Guide 185

4

186

Introduction to the Frame API

Using old clients with FDK 12

FDK Programmer’s Guide

5

API Client Initialization

..................................
.....

2

This chapter describes how to start interaction between your client and FrameMaker.

Responding to the FrameMaker product’s initialization call
When the FrameMaker product starts, it attempts to start all the clients registered with
it,1 except document reports and filters. The FrameMaker product attempts to start each
client by calling its F_ApiInitialize() callback function.
Your client should define F_ApiInitialize() as follows:
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
/* Your client code goes here */
}
This argument

Means

initialization

A flag that indicates the type of initialization (see “Initialization
types”)

Usually, you want your client to do something immediately after the user starts the
FrameMaker product. For example, you may want to add menus to the menu bar or
request notification for certain events. To do this, you call API functions from the
F_ApiInitialize() function. For information on creating menus and requesting
notification, see Chapter 3, “Creating Your Client’s User Interface.”

.................................
1. For information on registering your client with a FrameMaker product, see the FDK Platform Guide for
your platform.

FDK Programmer’s Guide 187

5

API Client Initialization

Initialization types

Suppose you want your client to display a dialog box after the FrameMaker product is
started. To do this, you could use the following F_ApiInitialize() function:
. . .
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
F_ApiAlert("Client has started.", FF_ALERT_CONTINUE_NOTE);
}
. . .

Initialization types
The following table summarizes the different types of initializations and the
initialization constants FrameMaker products can pass to your client’s
F_ApiInitialize() callback.
When F_ApiInitialize
is called

Initialization constant

FrameMaker product
starts with no special
options

After starting

FA_Init_First

All except document
reports and filters

FrameMaker product
starts with take-control
client

After starting

FA_Init_First

All except document
reports and filters

After all clients have
finished processing the
FA_Init_First
initialization

FA_Init_TakeControl

All clients set up as
take-control clients

Document report chosen
from Document Reports
dialog box

After report is chosen

FA_Init_DocReport

The chosen document
report

Notification, menu
choice, or hypertext
command for a client
that has bailed out

When the menu item is
chosen, the hypertext
command is clicked, or
the notification should
be issued

FA_Init_Subsequent

Clients that have
bailed out and are
waiting for an event,
menu choice, or
hypertext command to
occur

Type of initialization

188

FDK Programmer’s Guide

Clients that receive
initialization

Initialization types

...

API Client Initialization

First initialization
When the user starts a FrameMaker product, the FrameMaker product calls the
F_ApiInitialize() function of each registered client (unless it’s a document report
or filter) with initialization set to FA_Init_First.

Take-control initialization
The FDK allows you to set up clients to receive a special initialization called a takecontrol or FA_Init_TakeControl initialization. The FrameMaker product issues
the FA_Init_TakeControl initialization after it has issued the FA_Init_First
initialization and all clients have returned control. This initialization is useful if you
want your client to conduct some batch processing after other clients have initialized,
but before the interactive user has control.
The FrameMaker product can issue the FA_Init_TakeControl initialization to
several clients. To set up a client to receive FA_Init_TakeControl initializations,
set the client’s type to TakeControl in the FrameMaker product .ini file.

Document report initialization
When a FrameMaker product is started, it does not attempt to initialize API clients that
are registered as document reports. It initializes a document report only when the user
chooses the document report from the Document Reports dialog box. When this occurs,
the FrameMaker product calls the document report’s F_ApiInitialize() callback
with initialization set to FA_Init_DocReport.
To appear in the Document Reports dialog box, a document report must be registered
with the FrameMaker product as a document report. For information on registering
document reports, see the FDK Platform Guide for your platform.

Filter initialization
If your client is registered as a filter, you should not define an F_ApiInitialize()
function for it. When the user opens or saves a file and selects your filter, the
FrameMaker product notifies your client by calling your client’s F_ApiNotify()
callback. For more information on F_ApiNotify() and notification, see
“Responding to user-initiated events or FrameMaker product operations” on page 217.
To receive notification, your filter must be registered as a filter. For information on
registering filters, see the FDK Platform Guide for your platform.

FDK Programmer’s Guide 189

5

API Client Initialization

Disabling the API

Initialization after a client has bailed out
If your API client is waiting for an event and not performing any
other processing, it can call F_ApiBailOut(). This exits your client’s process and
frees all the system resources that it uses. If an event that
your client is waiting for occurs, the FrameMaker product restarts your client by calling
its F_ApiInitialize() function with initialization set to
FA_Init_Subsequent.
A document report should always bail out after it completes processing, because the
API initializes it each time the user chooses it from the Document Reports dialog box.
A filter should always bail out after it filters a file, because the API initializes it each
time a filterable file is opened, imported, or saved.
For more information on F_ApiBailOut(), see “F_ApiBailOut()” on page 84 of the
FDK Programmer’s Reference.

Disabling the API
The user can disable all API clients before starting theFrameMaker product by changing
the API=On setting in the FrameMaker product .ini file to API=Off.
..............................................................................

IMPORTANT: Many FrameMaker features are implemented via API clients. If you
disable the API then you also disable these features. Such features include XML and
SGML import and export, Save As HTML, and Word Count.
..............................................................................

FrameMaker Product Activation by Asynchronous Clients
Asynchronous clients on Windows that launch a FrameMaker process and wait for it to
become idle (by calling WaitForInputIdle) before attempting to connect using
F_ApiWinConnectSession need to make provision for the connection time required
during activation as explained below.
If FrameMaker has not been activated (relevant only for the FrameMaker Point Product
on Windows XP and Windows Vista®), an activation screen prompts the user for input.
The WaitForInputIdle call returns at this point while FrameMaker isn’t actually
ready for communication. Therefore, the client must give the user enough time to
activate or skip activation before attempting to connect to FrameMaker using
F_ApiWinConnectSession. Otherwise, the client can require the user to activate the
product before using it. Despite activation, WaitForInputIdle returns too early
before FrameMaker is actually ready to establish a connection. The issue can be
resolved by modifying the code and introducing a 5-10 second sleep before attempting
to connect to the FrameMaker session.
190

FDK Programmer’s Guide

FrameMaker Product Activation by Asynchronous Clients

...

API Client Initialization

Another solution is to attempt to connect a multiple or indefinite number of times with
short sleeps in between.
Asynchronous clients running the FrameMaker Point Product on Windows 2000 or
running the FrameMaker Server on Windows 2000, XP, or VISTA won’t encounter any
such problems.

FDK Programmer’s Guide 191

5

192

API Client Initialization

FrameMaker Product Activation by Asynchronous Clients

FDK Programmer’s Guide

6

Creating Your Client’s
User Interface

..................................
.....

3

This chapter describes how to use the Frame API to create a user interface for your FDK
client.
Your client can interact with the user in the following ways:


By displaying its own dialog boxes



By implementing its own menus, menu items, and keyboard shortcuts



By responding to the message apiclient hypertext command



By responding to user-initiated events or FrameMaker product operations



By implementing quick-key commands

The following sections discuss these ways of interacting with the user in greater detail.

Using API dialog boxes to prompt the user for input
The Frame API provides a variety of premade dialog boxes. All of these dialog boxes
are modal—the user must dismiss them before continuing. The following sections
discuss how to use these dialog boxes.
The API also allows you to create and use custom modal and modeless dialog boxes.
For more information, see Chapter 10, “Creating Custom Dialog Boxes for Your
Client” and Chapter 11, “Handling Custom Dialog Box Events.”

FDK Programmer’s Guide 193

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using API dialog boxes to prompt the user for input

Using alert boxes
To display a dialog box with a short message, use F_ApiAlert().
The syntax for F_ApiAlert() is:
IntT F_ApiAlert(StringT message,
IntT type);
This argument

Means

message

The message that appears in the alert box

type

The type of alert box

Specify one of the following values for the type argument.
type constant

Type of dialog box displayed

FF_ALERT_OK_DEFAULT

Displays OK and Cancel buttons; OK is the default

FF_ALERT_CANCEL_DEFAULT

Displays OK and Cancel buttons; Cancel is the default

FF_ALERT_CONTINUE_NOTE

Displays Continue button

FF_ALERT_CONTINUE_WARN

Displays Continue button with a warning indication

FF_ALERT_YES_DEFAULT

Displays Yes and No buttons; Yes is the default

FF_ALERT_NO_DEFAULT

Displays Yes and No buttons; No is the default

F_ApiAlert() returns 0 if the user clicks OK, Continue, or Yes; otherwise, it
returns a nonzero value.

194

FDK Programmer’s Guide

Using API dialog boxes to prompt the user for input

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Example
The following code displays the alert box shown in Figure 3-1:
. . .
IntT err;
err = F_ApiAlert((StringT)"This alert is an OK_DEFAULT.",
FF_ALERT_OK_DEFAULT);
. . .

Figure 3-1 FF_ALERT_OK_DEFAULT alert box

Using string, integer, and metric input dialog boxes
To prompt the user for a single string, integer, or metric value, use
F_ApiPromptString(), F_ApiPromptInt(), or F_ApiPromptMetric().
These functions all allow you to provide a default value for the entry field.
Their syntax is:
IntT F_ApiPromptString(StringT *stringp,
StringT message,
StringT stuffVal);
IntT F_ApiPromptInt(IntT *intp,
StringT message,
StringT stuffVal);
IntT F_ApiPromptMetric(MetricT *metricp,
StringT message,
StringT stuffVal,
MetricT defaultunit);
This argument

Means

stringp, intp,
or metricp

A pointer to the user variable that gets the return value from the input field
when the user clicks OK.

message

The message that appears in the dialog box.

FDK Programmer’s Guide 195

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using API dialog boxes to prompt the user for input

This argument

Means

stuffVal

The default value that appears in the input field when the dialog box is
first displayed. It must be a string for integer and metric prompts, as well
as string prompts.

defaultunit

The metric unit to use if the user doesn’t specify one. For example, to use
inches as the default unit, specify 4718592. For more information on
metric values, see “MetricT values” on page 950 of the FDK
Programmer’s Reference.

These functions all return 0 if the user clicks OK. Otherwise, they return a nonzero
error value. If the user clicks Cancel, the API does not assign a value to *stringp,
*intp, or *metricp.
If the user types alphabetic text after a number in an F_ApiPromptInt() dialog box,
the API ignores the text and just returns the number. For example, if the user types 10
cookies, the returned value is 10.
F_ApiPromptMetric() dialog boxes behave like metric dialog boxes in the user
interface. If the user types a number followed by a string that represents a unit, the API
converts the value into the equivalent number of metric units. For example, if the user
types 5in or 5", the API returns 5*(4718592). If the user doesn’t specify a unit,
the API uses the unit specified by defaultunit.
..............................................................................

IMPORTANT: F_ApiPromptString() allocates memory for the string referenced
by *stringp. Use the FDK function F_ApiDeallocateString() to free the string when
you are done with it.
..............................................................................

196

FDK Programmer’s Guide

Using API dialog boxes to prompt the user for input

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Examples
The following code displays the dialog box shown in Figure 3-2:
. . .
#include "fmemory.h"
IntT err;
StringT sres;
err = F_ApiPromptString(&sres, (StringT)"String?",
(StringT)"Default text");
if (err) return;
/* Some code to use the string goes here. */
F_ApiDeallocateString(&sres);
. . .

Figure 3-2 String prompt dialog box

The following code displays the dialog box shown in Figure 3-3:
. . .
#include "futils.h" /* Provides declaration for F_Sprintf(). */
IntT err, ires;
UCharT msg[256];
err = F_ApiPromptInt(&ires, (StringT)"Integer?", "1234");
if (err) F_Sprintf(msg,(StringT)"Cancelled, ires has no value");
else F_Sprintf(msg,(StringT)"The value of ires is %d.",ires);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
. . .

Figure 3-3 Integer prompt dialog box

FDK Programmer’s Guide 197

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using API dialog boxes to prompt the user for input

The following code displays the dialog box shown in Figure 3-4:
. . .
#define IN (MetricT) 65536*72 /* Default unit (inches) */
IntT err;
MetricT mres;
err = F_ApiPromptMetric(&mres, (StringT)"Metric?",
"12.34in", IN);
. . .

Figure 3-4 Metric prompt dialog box

Using file selection dialog boxes
To display dialog boxes similar to theFrameMaker product’s Open and Save dialog
boxes, use F_ApiChooseFile(). F_ApiChooseFile() displays files and
directories in a scrolling list and allows the user to choose a file or directory.
The syntax for F_ApiChooseFile() is:
IntT F_ApiChooseFile(StringT *choice,
StringT title,
StringT directory,
StringT stuffVal,
IntT mode,
StringT helpLink);

198

FDK Programmer’s Guide

Using API dialog boxes to prompt the user for input

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

This argument

Means

choice

The selected pathname when the user clicks OK.

title

The message that appears in the dialog box.

directory

The default directory when the dialog box is first displayed. If you specify
an empty string, the last directory used by your client is used. If your client
hasn’t used any directories, the directory specified by the session property,
FP_OpenDir, is used.

stuffVal

The default value that appears in the input field when the dialog box first
appears. If the dialog box type specified by mode doesn’t have an input
field, this string is ignored.

mode

A constant specifying the type of dialog box. For a list of dialog box types,
see “F_ApiChooseFile()” on page 89 of the FDK Programmer’s Reference.

helpLink

Obsolete in versions 6.0 and later; pass an empty string. The name of a
document containing help information for the dialog box and an optional
hypertext link.

..............................................................................

IMPORTANT: F_ApiChooseFile() allocates memory for the string referenced by
*choice. Use F_ApiDeallocateString() to free the string when you are done
with it.
..............................................................................

FDK Programmer’s Guide 199

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using API dialog boxes to prompt the user for input

Example
To create the dialog box shown in Figure 3-5, add the following code to your client:
. . .
#include "futils.h"
#include "fmemory.h"

IntT err;
StringT sres;
UCharT msg[256];
err = F_ApiChooseFile(&sres, (StringT)"Choose a file",
(StringT)"/tmp", (StringT)"",
FV_ChooseSelect, (StringT)"");
if (err)
F_Sprintf(msg,(StringT)"Cancelled, sres is not defined.");
else
F_Sprintf(msg,(StringT)"The value of sres is %s.",sres);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
if (!err) F_ApiDeallocateString(&sres);
. . .

Figure 3-5 File selection dialog box

200

FDK Programmer’s Guide

Using API dialog boxes to prompt the user for input

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using scroll list dialog boxes
To display a scroll list dialog box, use F_ApiScrollBox(). F_ApiScrollBox()
displays an array of items that you provide and allows the user to choose one.
The syntax for F_ApiScrollBox() is:
IntT F_ApiScrollBox(IntT *selected_item,
StringT title,
F_StringsT *stringslist,
IntT default);
This argument

Means

selected_item

The index of the selected item when the user clicks OK (or double-clicks
an item). The index of the first item is 0.

title

The title that appears on the dialog box.

stringslist

The list of items that appears in the scroll list.

default

The index of the item that is selected when the dialog box first appears.
For no default, specify -1.

F_StringsT is defined as:
typedef struct {
UIntT len; /* Number of strings */
StringT *val; /* Array of strings */
} F_StringsT;

The F_ApiScrollBox() function returns a nonzero value if the user clicks Cancel
or an error occurs, or 0 if the user clicks OK.

FDK Programmer’s Guide 201

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using API dialog boxes to prompt the user for input

Example
To create the dialog box shown in Figure 3-6, add the following code to your client:
. . .
#include "futils.h"
IntT err, choice, listLen = 3;
UCharT msg[256];
F_StringsT colors;
colors.val = (StringT *) F_Alloc(listLen*sizeof(StringT),
NO_DSE);
if (colors.val) {
colors.len = (UIntT)listLen;
colors.val[0] = F_StrCopyString("red");
colors.val[1] = F_StrCopyString("green");
colors.val[2] = F_StrCopyString("blue");
err = F_ApiScrollBox(&choice, "Choose a color.", &colors,
0);
if (!err)
F_Sprintf(msg, "The choice is %s.", colors.val[choice]);
else
F_Sprintf(msg, "Cancel was pressed");
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
F_ApiDeallocateStrings(&colors);
}
. . .

Figure 3-6 Scroll list dialog box

202

FDK Programmer’s Guide

Using commands, menu items, and menus in your client

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using commands, menu items, and menus in your client
The API allows you to use commands, menu items, and menus in your client’s user
interface. A command is a part of FrameMaker product or FDK client functionality that
a user can invoke by typing a shortcut. A menu item is an instance of a command that
appears on a menu. There can be several menu items for each command.
A menu is a list of menu items or other menus. A menu bar is a list of menus that appears
at the top of the FrameMaker window on Windows platforms.
To use commands and menus in your client’s user interface, follow these general steps:
1. Get the IDs of the FrameMaker product menu bars and menus that you want to add
your client’s menus and commands to.
2. Define your client’s commands and add them to menus.
3. Define your client’s menus and add them to FrameMaker product menus or
menu bars.
4. Write an F_ApiCommand() callback to respond to the user invoking your client’s
commands.
These steps are discussed in greater detail in the following sections.

Getting the IDs of FrameMaker product menus and menu bars
To get the IDs of commands, menus, or menu bars, use F_ApiGetNamedObject().
The syntax for F_ApiGetNamedObject() is:
F_ObjHandleT F_ApiGetNamedObject(F_ObjHandleT parentId,
IntT objType,
StringT objName);
This argument

Means

parentId

The ID of the document, book, or session containing the object for which
you want to get an ID. For commands and menus, it is always
FV_SessionId.

objType

The object type. To get the ID of a command, specify FO_Command. To get
the ID of a menu or menu bar, specify FO_Menu.

objName

The name of the command, menu, or menu bar. This name may not be the
same as the label or title that appears on a menu.

The menu and command names you can specify for objName depend
on how the user has customized the menus. The [Files] section of the maker.ini file

FDK Programmer’s Guide 203

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using commands, menu items, and menus in your client

specifies the location of the menu and command configuration files that list
FrameMaker’s menus and commands.
The following table lists some FrameMaker product menus and the names you use to
specify them:
Menu title

Name

Edit

EditMenu

Element

ElementMenu

File

FileMenu

Format

FormatMenu

Graphics

GraphicsMenu

Special

SpecialMenu

Table

TableMenu

View

ViewMenu

Help

!HelpMenu

The following table lists the names of some FrameMaker product menu bars. Menu bar
names starting with an exclamation point (!) can’t be removed by the user.

204

FrameMaker product menu bar

Name

Menu bar for documents (complete menus)

!MakerMainMenu

Menu bar for documents (quick menus)

!QuickMakerMainMenu

Menu bar for books (complete menus)

!BookMainMenu

Menu bar for books (quick menus)

!QuickBookMainMenu

View-only menu bar

!ViewOnlyMainMenu

FDK Programmer’s Guide

Using commands, menu items, and menus in your client

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Example
The following code gets the ID of the Edit menu and the view-only menu bar:
. . .
F_ObjHandleT editMenuId, viewOnlyMenuBarId;
editMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"EditMenu");
viewOnlyMenuBarId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"!ViewOnlyMainMenu");
. . .

Defining commands and adding them to menus
To define a command and add it to a menu, use F_ApiDefineAndAddCommand().
The syntax for F_ApiDefineAndAddCommand() is:
F_ObjHandleT F_ApiDefineAndAddCommand(IntT cmd,
F_ObjHandleT toMenuId,
StringT name,
StringT label,
StringT shortcut);
This argument

Means

cmd

The integer that the FrameMaker product passes to your client’s
F_ApiCommand() function when the user chooses the menu item or types
the keyboard shortcut for the command.

toMenuId

The ID of the menu to which to add the command.

name

A unique name to identify the command.

label

The title of the command as it appears on the menu.

shortcut

The keyboard shortcut sequence. Many FrameMaker product commands
use shortcuts beginning with Esc (\!). To specify Esc when you create a
command, use \\! in the string you pass to shortcut.

F_ApiDefineAndAddCommand() returns the ID of the command it creates.

FDK Programmer’s Guide 205

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using commands, menu items, and menus in your client

Example
The following code defines a command with the shortcut Esc N L and adds it to the
Utilities menu:
. . .
#define NUMBER_LINES 1
F_ObjHandleT utilsMenuId, cmdId;
utilsMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"UtilitiesMenu");
cmdId = F_ApiDefineAndAddCommand(NUMBER_LINES, utilsMenuId,
"NumberLines","Number lines", "\\!NL");
. . .

Figure 3-7 Utilities menu with client-defined menu item

Defining and adding menus
To define a menu and add it to a menu bar or another menu, use
F_ApiDefineAndAddMenu(). The syntax for F_ApiDefineAndAddMenu() is:
F_ObjHandleT F_ApiDefineAndAddMenu(F_ObjHandleT toMenuId,
StringT name,
StringT label);
This argument

Means

toMenuId

The ID of the menu or menu bar to which to add the new menu

name

A unique name that identifies the new menu

label

The title of the new menu as it appears on the menu or menu bar

F_ApiDefineAndAddMenu() returns the ID of the menu it creates.
If you specify a menu bar ID for toMenuId, the FrameMaker product implements the
new menu as a pull-down menu. If you specify a pull-down or a pop-up menu ID for
toMenuId, the FrameMaker product implements the new menu as a pull-right menu.

206

FDK Programmer’s Guide

Using commands, menu items, and menus in your client

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

..............................................................................

IMPORTANT: Your menu appears only on the menu bar you specify. For example, if you
add a menu only to the !MakerMainMenu menu bar, the menu will not appear if the
user switches to quick menus. For your menu to appear after the user has switched to
quick menus, you must also add it to the !QuickMakerMainMenu menu bar.
..............................................................................

Adding commands to a menu that you have created
To add a command to a menu that you have created, call
F_ApiDefineAndAddCommand() with toMenuId set to the ID returned by the
F_ApiDefineAndAddMenu() call that created the menu. For example, the following
code defines a menu and adds it to the FrameMaker document menu bar. Then it adds
some commands to the menu.
. . .
#define CHECK

1

#define PRINT

2

F_ObjHandleT menubarId, menuId, cmd1Id, cmd2Id;
/* Get the ID of the FrameMaker main menu bar. */
menubarId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"!MakerMainMenu");
/* Define and add the menu to the main menu. */
menuId = F_ApiDefineAndAddMenu(menubarId, "GrammarMenu",
"Grammar");
/* Define some commands and add them to the menu. */
cmd1Id = F_ApiDefineAndAddCommand(CHECK, menuId,
"CheckGrammar","Check Grammar", "\\!CG");
cmd2Id = F_ApiDefineAndAddCommand(PRINT, menuId,
"PrintErrors","Print Errors", "\\!PE");
. . .

Figure 3-8 FrameMaker main menu bar and a client-defined menu

FDK Programmer’s Guide 207

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using commands, menu items, and menus in your client

Example
The following code defines a menu and adds it to the Edit menu:
. . .
#define CHECK

1

#define PRINT

2

F_ObjHandleT editMenuId, menuId, cmd1Id, cmd2Id;
/* Get the ID of the edit menu. */
editMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"EditMenu");
/* Define the menu and add it to the Edit menu. */
menuId = F_ApiDefineAndAddMenu(editMenuId, "GrammarMenu",
"Grammar");
/* Define some commands and add them to the menu. */
cmd1Id = F_ApiDefineAndAddCommand(CHECK, menuId,
"CheckGrammar","Check Grammar", "\\!CG");
cmd2Id = F_ApiDefineAndAddCommand(PRINT, menuId,
"PrintErrors","Print Errors", "\\!PE");
. . .

Figure 3-9 Edit menu with a client-defined pull-right menu

208

FDK Programmer’s Guide

Using commands, menu items, and menus in your client

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to the user choosing a command
Whenever the user chooses a menu item or types a keyboard shortcut for a command
created by your client, the FrameMaker product attempts to call your client’s
F_ApiCommand() function. Your client should define this function as follows:
VoidT F_ApiCommand(command)
IntT command;
{
/* Code to respond to command choices goes here. */
}
This argument

Means

command

The value of the cmd parameter in the F_ApiDefineAndAddCommand()
call that created the command that the user chose

FDK Programmer’s Guide 209

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using commands, menu items, and menus in your client

Example
The following client defines some commands and adds them to the Special menu. It
provides an F_ApiCommand() function to respond to the user choosing the
commands.
#include "fapi.h"
#define LOAD 1
#define QUERY 2

VoidT F_ApiInitialize(initialization)
IntT initialization;
{
F_ObjHandleT specialMenuId;
/* Get the ID of the special menu. */
specialMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"SpecialMenu");
/* Define the commands and add them to the Special menu. */
F_ApiDefineAndAddCommand(LOAD, specialMenuId,
"LoadDatabase", "Load Database","");
F_ApiDefineAndAddCommand(QUERY, specialMenuId,
"QueryDatabase", "Query Database", "");
}
VoidT F_ApiCommand(command)
IntT command;
{
switch(command)
{
case LOAD:
/* Code to load database goes here. */
break;
case QUERY:
/* Code to query database goes here. */
break;
}
}

210

FDK Programmer’s Guide

Replacing FrameMaker product menus and commands

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Replacing FrameMaker product menus and commands
You can replace FrameMaker product menus and commands with your own menus and
commands by calling F_ApiDefineAndAddCommand() and
F_ApiDefineAndAddMenu() with the name parameter set to the name of a
FrameMaker product menu or command.
For example, the following code replaces the FrameMaker product Print command:
. . .
#define PRINT_CMD 223
F_ObjHandleT fileMenuId, printCmdId;
fileMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"FileMenu");
printCmdId = F_ApiDefineAndAddCommand(PRINT_CMD, fileMenuId,
"Print", "Print...", "\\!fp");
. . .

If you use this code, the Print command appears on the File menu exactly as it normally
would. However, when the user chooses it, the FrameMaker product never executes the
Print operation. Instead, it calls your client’s F_ApiCommand() callback with
command set to PRINT_CMD. The F_ApiCommand() callback can execute your own
version of the Print operation. For example, it can set the default number of copies to 1
and then call F_ApiSilentPrintDoc() to print the document. This prevents the
user from printing more than one copy of a document at a time.

Allowing users to configure your client’s interface
When you call F_ApiDefineAndAddCommand() and specify the name of a
command that is already defined in the user’s menu configuration files, the FrameMaker
product gives precedence to the definition in the configuration files. If the configuration
files assign a label or a shortcut to the command, the FrameMaker product uses it
instead of the one you specify. If the command is already a menu item, the FrameMaker
product ignores the menu that you specify and leaves the menu item where it is.

FDK Programmer’s Guide

211

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Allowing users to configure your client’s interface

For example, if the Print command is already defined and appears on the File menu, the
following code has the same effect as the sample code in the previous section:
. . .
#define PRINT_CMD 223
F_ObjHandleT printCmdId, bogusMenuId = 12345;
printCmdId = F_ApiDefineAndAddCommand(PRINT_CMD, bogusMenuId,
"Print", "This is ignored", "This too");
. . .

If you use this code, the Print command appears on the File menu exactly as it normally
does.
Because FrameMaker products give precedence to the labels, shortcuts, and menu item
locations specified by the menu configuration files, users can configure your client’s
interface. If users know the names of your client’s commands, they can assign labels
and shortcuts to the commands and specify where the commands appear on the menus
by editing their menu configuration files.
For example, if your client defines a command with the following code:
. . .
F_ObjHandleT editMenuId;
editMenuId = F_ApiGetNamedObject(FV_SessionId, FO_Menu,
"EditMenu");
F_ApiDefineAndAddCommand(1, editMenuId,
"NumberLines","Number Lines", "\\!NL");
. . .

users can make the command appear on the Special menu instead of the Edit menu by
adding the following line to their menu configuration files:

>

If users add this line to their menu configuration files and your client does not define the
NumberLines command or is not running, the NumberLines menu item appears
dimmed.
..............................................................................

IMPORTANT: Adobe Systems recommends that you document the names of your client’s
menus and commands so that users can customize them.
..............................................................................

212

FDK Programmer’s Guide

Using hypertext commands in your client’s user interface

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

For more information on using menu configuration files, see the online manual,
Customizing FrameMaker Products. For more information on changing commands,
menu items, and menus, see Chapter 9, “Manipulating Commands and Menus with the
API.”

Using hypertext commands in your client’s user interface
You can embed hypertext commands in markers within FrameMaker product
documents. A FrameMaker product’s basic set of hypertext commands allows you to
establish links within and between documents and to jump from link to link.
You can lock a FrameMaker product document that contains hypertext commands so
that it behaves like a command palette. For information on locking documents, see your
FrameMaker product user documentation. Documents have a set of properties that
specify their characteristics when they are locked. By setting these properties, you can
change how a locked document window appears. For example, you can hide the scroll
bars and the window control buttons. For a list of locked document properties, see
“Document View Only properties” on page 821 of the FDK Programmer’s Reference.
FrameMaker products provide a special hypertext command, message apiclient,
that can send messages to your client. With this command, you can create an extremely
flexible user interface. Your client only needs to define responses for the hypertext
messages that are sent to it. Users and hypertext document designers can set up the
interface that sends the messages. The message apiclient hypertext command is
especially useful for setting up command palettes for your client.
To use the message apiclient hypertext command in your client’s interface,
follow the general steps below:
1 Set up the hypertext commands.
2 Create a function named F_ApiMessage() in your client to respond to the user
clicking a hypertext marker that contains a message apiclient command.
These steps are discussed in greater detail in the following sections.

FDK Programmer’s Guide 213

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using hypertext commands in your client’s user interface

Setting up hypertext commands
The syntax for message apiclient is:
message apiclient yourmessage
This argument

Means

apiclient

The name under which the client is registered with the FrameMaker product.
It is the ClientName specified in the [APIClients] section of the
maker.ini file.

yourmessage

The string that the FrameMaker product passes to the API client.

When the user clicks a hypertext command, the FrameMaker product calls the
F_ApiMessage() function of the client specified by apiclient and passes the
string specified by yourmessage to the client.

Responding to message apiclient commands
To respond to the message apiclient hypertext command, your client must define
F_ApiMessage() as follows:
VoidT F_ApiMessage(message, docId, objId)
StringT message;
F_ObjHandleT docId;
F_ObjHandleT objId;
{
/* Code to respond to hypertext message goes here. */
}

214

This argument

Means

message

The string from the hypertext command message

docId

The ID of the document containing the hypertext marker

objId

The ID of the hypertext marker the user clicked

FDK Programmer’s Guide

Using hypertext commands in your client’s user interface

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Example
Suppose you want to create a command palette with two arrows in it. When the user
clicks an arrow, it changes the fill pattern of a selected graphic object in the active
document. To make this command palette, create a document with the graphics shown
in Figure 3-10.

Figure 3-10 Example hypertext markers

Assuming your client is registered with the FrameMaker product as myapi, insert the
following hypertext markers into the document:


In the text column around the up arrow: message myapi 1



In the text column around the down arrow: message myapi 2

Save the document in View Only format.

FDK Programmer’s Guide 215

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Using hypertext commands in your client’s user interface

To respond to the user clicking one of the arrows, add the following code to your client:
. . .
#define UPARROW

1

#define DOWNARROW 2

VoidT F_ApiMessage(message, docId, objId)
StringT message;
F_ObjHandleT docId;
F_ObjHandleT objId;
{
F_ObjHandleT targetDocId, targetGraphicId;
IntT fillpatt;
/* Get ID of active document. Note that View Only documents
* are not considered active.
*/
targetDocId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of selected object in active document. */
targetGraphicId = F_ApiGetId(targetDocId, targetDocId,
FP_FirstSelectedGraphicInDoc);
if(!targetGraphicId) return;
/* Get selected object’s current fill pattern. */
fillpatt = F_ApiGetInt(targetDocId, targetGraphicId, FP_Fill);
switch(atoi(message))
{
case UPARROW:
/* Only 16 patterns available, so reset at 16. */
if (++fillpatt == 16) fillpatt = 0; break;
case DOWNARROW:
if (--fillpatt == 0) fillpatt = 15; break;
}
/* Set the fill pattern of the selected graphic. */
F_ApiSetInt(targetDocId, targetGraphicId, FP_Fill, fillpatt);
}
. . .

For this example client to work, you should have the View Only document and one
normal document open. Select a graphic in the normal document, then click one of the
hypertext markers in the View Only document.

216

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations
Your client can respond when the user initiates certain events or FrameMaker product
operations. For example, you may want your client to archive an extra copy of a
document each time the user saves it, or to display a special dialog box when the user
exits a document.
To make your client respond to events, follow these general steps:
1 Request notification for the events.
2 Create a callback function named F_ApiNotify() to respond to the events.
These steps are discussed in greater detail in the following sections.

Requesting notification for events
To receive notification for a particular event, your client must request it by calling
F_ApiNotification().
The syntax for F_ApiNotification() is:
IntT F_ApiNotification(IntT notification,
IntT state);
This argument

Means

notification

A constant that specifies the notification point. See the table below for a
list of the constants.

state

Specifies whether to turn notification for the notification point on or off.
Specify True to request notification or False to turn notification off.

FDK Programmer’s Guide 217

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations

For most events, there are several notification points, or stages in the event when the
FrameMaker product can notify your client. For example, when the FrameMaker
product saves a file, there are two notification points: one immediately before and one
immediately after it saves the file. The following table lists the notification points and
constants the FrameMaker product passes to F_ApiNotify() for some events.
Event or operation

Notification points

Notification constants

Frame binary
document opened

Before checking the type of
the file to be opened

FA_Note_PreFileType

After checking the type of
the file to be opened

FA_Note_PostFileType

Before opening the file

FA_Note_PreOpenDoc

After opening the file

FA_Note_PostOpenDoc

Filterable document
opened

Before checking the type of
the file to be opened

FA_Note_FilterIn

Document saved in
Frame binary format

Before saving the document

FA_Note_PreSaveDoc

After saving the document

FA_Note_PostSaveDoc

Document saved as
filterable type

Before saving the document

FA_Note_FilterOut

Document exited

Before exiting the document

FA_Note_PreQuitDoc

After exiting the document

FA_Note_PostQuitDoc

For a complete list of events and notification points, see “F_ApiNotification()” on
page 333 of the FDK Programmer’s Reference.
You can request notification in your client’s F_ApiInitialize() callback or
anywhere you want in your client.

218

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Example
Suppose you want a FrameMaker product to notify your client whenever the user exits
a document. To request this notification when your client is first started, write the
F_ApiInitialize() callback as follows:
. . .
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
/* Request notification for exit. */
if (initialization == FA_Init_First)
F_ApiNotification(FA_Note_PreQuitDoc, True);
}
. . .

Requesting notification for API filters
API client filters do not need to request notification. To receive filter notifications,
filters only need to be registered with the FrameMaker product. If they are correctly
registered, filters receive the following notifications:
This type of filter

Receives this notification

Import

FA_Note_FilterIn

Export

FA_Note_FilterOut

For more information on writing client filters, see “Writing filter clients” on page 472
of the FDK Programmer’s Guide. For more information on registering filters, see the
FDK Platform Guide for your platform.

FDK Programmer’s Guide 219

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations

Adding the F_ApiNotify() callback
The FrameMaker product notifies your client of events for which it has requested
notification by calling its F_ApiNotify() function. Your client should define
F_ApiNotify() as follows:
VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm;
{
/* Code that responds to notifications goes here. */
}
This argument

Means

notification

A constant that indicates the event and the notification point (see the table
on page 218 for a list of the constants).

docId

The ID of the active document when the event occurs. For filters, the
document into which the filter should import its data; if this is zero, the
filter must create a new document.

sparm

The string, if any, associated with the notification. For example, if the
notification is for an Open or Save, sparm specifies the pathname of the
affected file.
If the notification is for text entry, sparm specifies the text the user
typed. Depending on how fast the user is typing, sparm may specify one
or several characters at a time.

iparm

The integer associated with the notification. For example, if
notification is FA_NotePreFunction or
FA_NotePostFunction, iparm specifies the f-code for the
command.

F_ApiNotify() can call API functions to get or set object properties or to initiate
FrameMaker product operations. The FrameMaker product calls F_ApiNotify()
only at the notification points for which your client has requested notification.

220

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

For example, the following code prints the name of each document the user opens to the
console:
. . .
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
if (initialization == FA_InitFirst)
F_ApiNotification(FA_Note_PostOpenDoc, True);
}

VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm;
{
if (notification == FA_Note_PostOpenDoc)
F_Printf(NULL, "The user opened: %s\n", sparm);
}
. . .

Canceling commands
Your client can cancel any command or action for which it receives a
FA_Note_PreNotificationPoint notification. For example, if it receives the
FA_Note_PreQuitDoc notification, it can cancel the Close command and prevent the
user from closing a document.

FDK Programmer’s Guide 221

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations

To abort a command, call F_ApiReturnValue(), with the parameter set to
FR_CancelOperation, when your client receives notification for the command. For
example, the following code cancels the Exit command, preventing the user from
closing any documents:
. . .
F_ApiNotification(FA_Note_PreQuitDoc, True);
. . .
VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm;
{
/* If user is trying to close document, cancel command. */
if (notification == FA_Note_PreQuitDoc)
F_ApiReturnValue(FR_CancelOperation);
}
. . .

Responding to text entry and actions that have no specific notifications
The API doesn’t provide specific notifications for most user actions. Instead, it provides
the following general notifications, which it issues for nearly every user action.

222

Event or operation

Notification points

Notification constants

Any user action that the
FrameMaker product
processes

After the FrameMaker
product finishes processing
the action

FA_Note_BackToUser

FrameMaker product
command invoked or
text entered in a
document

Before the FrameMaker
product executes the
command or adds text to the
document

FA_Note_PreFunction

After the FrameMaker
product executes the
command or adds text to the
document

FA_Note_PostFunction

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

The API issues the FA_NoteBackToUser notification after any user action the
FrameMaker product processes, including insertion point changes, selection changes,
and text entry. This notification is useful if you need to update a modeless dialog box
containing settings that are dependent on the insertion point.
When the API issues the FA_NoteBackToUser notification, it indicates only that an
action occurred; it does not specify which action. If you want to respond to specific
actions, use the FA_Note_PreFunction or the FA_Note_PostFunction
notification instead of FA_NoteBackToUser.
..............................................................................

IMPORTANT: When the FrameMaker product performs a book-wide command (a
command that process all documents in a book), it posts an FA_NotePreFunction and
FA_NotePostFinction notification for the book file, and for each document in the book.
When trapping book-wide frunctions, you should check the value of docId to
determine whether it indicates a document or the active book.
For example, if you search a book with two documents in it, the FrameMaker product
posts the following funtion notifications:
FA_Note_PreFunction (start searching book)
FA_Note_PreFunction (start searching first document)
FA_Note_PostFunction (stop searching first document)
FA_Note_PreFunction (start searching second document)
FA_Note_PostFunction (stop searching second document)
FA_Note_PostFunction (stop searching book)
..............................................................................

When the API issues an FA_Note_PreFunction or FA_Note_PostFunction
notification, it specifies the user action by setting iparm to a function code (f-code).
An f-code is a hexadecimal code that specifies a command or other user action. The
following table shows some common f-codes and the commands or user actions they
specify.
F-code

Command or user action

PGF_APPLY_TAG

The user applied a paragraph format

CHAR_APPLY_TAG

The user applied a character format

TXT_10

The user set the text size to 10 points

KBD_OPEN

The user chose Open

KBD_INPUT

The user typed some text

KBD_ALIGN

The user chose Align

FDK Programmer’s Guide 223

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations

For a complete list of f-codes, see the fcodes.h file shipped with the FDK.
If a user action is associated with a text string, the API passes the string
to the sparm parameter of your client’s F_ApiNotify() function. For example,
when the user types text, the API sets sparm to the text the user typed.

224

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

The following table lists some f-codes and the strings that are associated with them.
F-code

Associated string that the API passes to sparm

PGF_APPLY_TAG

The name of the paragraph format the user applied.

CHAR_APPLY_TAG

The name of the character format the user applied.

KBD_INPUT

The text the user typed. It can be one or more characters depending on
how fast the user types.

TXT_FAMILY_AND
_VARIATION

The name of the font family the user chose.

Your client can cancel any action for which it receives the FA_Note_PreFunction
notification by calling F_ApiReturnValue() with retVal set to
FR_CancelOperation. Your client can even cancel text entry.
For example, the following code intercepts any text the user attempts to type in a
document and prints it to the console:
. . .
#include "fcodes.h"
/* Turn on notification. */
F_ApiNotification(FA_Note_PreFunction, True);
. . .
VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm;
{
if (notification == FA_Note_PreFunction
&& iparm == KBD_INPUT)
{
F_Printf(NULL,"The user typed: %s\n", sparm);
/* Prevent text from being added to document. */
F_ApiReturnValue(FR_CancelOperation);
}
}
. . .

Responding to events initiated by API clients
A FrameMaker product notifies your client of any event that it has requested
notification for. The event can be initiated directly by the user or by another client.
FDK Programmer’s Guide 225

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Responding to user-initiated events or FrameMaker product operations

The Frame API provides a set of functions that allow API clients to programmatically
execute Open, Save, and several other FrameMaker product operations. For more
information on these functions, see Chapter 4, “Executing Commands with API
Functions.” When a client executes an operation with one of these functions, the
FrameMaker product notifies all the other API clients that have requested notification
for that event1. It does not, however, notify the client that executed the operation. For
example, to have your client automatically make an additional copy of a document
when the user saves it, use the following code:
. . .
/* Turn on notification. */
F_ApiNotification(FA_Note_PostSaveDoc, True);
. . .
VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm;
{
/* After the document has been saved, save another copy. */
if (notification == FA_Note_PostSaveDoc)
F_ApiSimpleSave(docId, "mybackup.doc", False);
}
. . .

In the example above, F_ApiNotify(), which responds to a Save notification, uses
F_ApiSimpleSave() to execute a Save operation itself. This does not result in
infinite recursion because the FrameMaker product does not notify the client of the Save
operation that it executes itself.

.................................
1. An API client can explicitly instruct a FrameMaker product to suppress notifications to other API clients
when it opens or saves a file by setting the FS_DontNotifyAPIClients property of the Open or Save
script to True. For more information on properties in the Open and Save scripts, see
“F_ApiGetOpenDefaultParams()” on page 212 and “F_ApiGetSaveDefaultParams()” on page 227 of the
FDK Programmer’s Reference.

226

FDK Programmer’s Guide

Responding to user-initiated events or FrameMaker product operations

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Handling notification for Open operations
The Open operation is more complex than most other operations. A FrameMaker
product does the following when it opens a file:
1 Determines whether the file is filterable.
If the file is filterable, the FrameMaker product issues the FA_Note_FilterIn
notification to the appropriate filter and abandons the Open operation. It is up to the
filter to finish opening the file. No other client receives any notification.
If the file is not filterable, the FrameMaker product continues with the Open operation.
2 Issues an FA_Note_PreFileType notification to all clients that have requested it.
This allows clients to uncompress a file if it is compressed, check it out if it is under
version control, or perform other operations that may change its type.
3 Checks the file’s type.
If the file is a type that the FrameMaker product can’t open, the FrameMaker product
displays a warning and cancels the Open operation. If the file is from a previous version
of a FrameMaker product, it prompts the user to convert the file or cancel the Open
operation.
4 Issues an FA_Note_PostFileType notification to all clients that have requested it.
5 Determines whether the file is a document or a book, and whether its format is Frame
binary or MIF.
6 Issues an FA_Note_PreOpenDoc, FA_Note_PreOpenBook,
FA_Note_PreOpenMIF, or FA_Note_PreOpenBookMIF notification.
7 Opens the document or book.
If the document or book is MIF, the FrameMaker product converts it.
8 Issues an FA_Note_PostOpenDoc, FA_Note_PostOpenMIF,
FA_Note_PostOpenBook, or FA_Note_PostOpenBookMIF notification.
Normally, you don’t request the FA_Note_PreFileType and
FA_Note_PostFileType notifications, because you don’t want to do anything with
a file before the FrameMaker product has checked its type. However, if you want to
change a file’s contents after the user has selected it but before the FrameMaker product
has checked its type, you should request notification for the FA_Note_PreFileType
notification point.

FDK Programmer’s Guide 227

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Implementing quick keys

For example, suppose you want to uncompress a compressed document file when the
user opens it. Normally, when a user attempts to open a compressed file, the
FrameMaker product displays an “Unrecognized type” alert and cancels the Open
operation when it checks the file’s type. You must uncompress the file after the user has
chosen it, but before the FrameMaker product checks its type. To do this, you could use
the following code:
. . .
F_ApiNotification(FA_Note_PreFileType, True);
. . .
VoidT F_ApiNotify(notification, docId, sparm, iparm)
IntT notification;
F_ObjHandleT docId;
StringT sparm;
IntT iparm
{
if (notification == FA_Note_PreFileType)
{
/* Code to test if file is compressed goes here. */
F_ApiAlert("Uncompressing file.", FF_ALERT_CONTINUE_NOTE);
/* Code to uncompress file goes here. */
}
}
. . .

Implementing quick keys
FrameMaker products provide a quick-key interface, which allows the user to choose
commands in the document Tag area. In FrameMaker, for example, the user can apply
a character format by pressing Esc q c. FrameMaker displays an f: prompt in the Tag
area. The user can then choose a character format by typing the first few letters of the
format’s name and pressing Return when the format appears in the Tag area.

228

FDK Programmer’s Guide

Implementing quick keys

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Your client can implement its own quick-key interface by calling
F_ApiQuickSelect(). The syntax for F_ApiQuickSelect() is:
IntT F_ApiQuickSelect(F_ObjHandleT docId,
StringT prompt,
F_StringsT *stringlist);
This argument

Means

docId

The ID of the document containing the Tag area in which to display the
prompt

prompt

The prompt that appears in the Tag area

stringlist

The list of strings from which the user can choose

F_ApiQuickSelect() returns the index of the string the user chose or -1 if the user
canceled the command.
For example, the following code implements the quick-key interface shown in
Figure 3-11:
. . .
F_StringsT fruits;
StringT strings[3];
IntT choice;
F_ObjHandleT docId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
strings[0] = (StringT)"Kumquat";
strings[1] = (StringT)"Durian";
strings[2] = (StringT)"Rambutan";
fruits.len = 3;
fruits.val = strings;
choice = F_ApiQuickSelect(docId, (StringT)"Fruit:", &fruits);
if (choice != -1)
F_Printf(NULL, (StringT)"The user chose: %s.\n",
strings[choice]);
. . .

Figure 3-11 Tag area with client-defined quick key

FDK Programmer’s Guide 229

7

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

Freeing system resources by bailing out

Freeing system resources by bailing out
Instead of leaving your client idle when it’s not executing, you may
want to free the system resources it uses. The API provides a function
named F_ApiBailOut(), which allows you to do this. When you call
F_ApiBailOut(), the FrameMaker product waits until your client returns from the
current callback, then exits your client, freeing the system resources it uses.
..............................................................................

IMPORTANT: Never call exit(), F_Exit(), or abort() from an API client. If
you call one of these functions, the function exits the FrameMaker product and
unpredictable results, including data loss, may occur.
..............................................................................

After it exits your client, the FrameMaker product continues processing events that
affect it. Your client’s menus remain on the menu bar and are still valid. If your client
has requested notification for particular events, the FrameMaker product continues to
monitor those events. The FrameMaker product also monitors message apiclient
hypertext commands that specify your client.
If the user chooses one of your client’s menu items or hypertext commands, or initiates
an event for which your client requested notification, the FrameMaker product restarts
your client, calling its F_ApiInitialize() function with initialization set
to FA_Init_Subsequent. After F_ApiInitialize() has returned control, the
FrameMaker product also calls the appropriate callback function for the menu choice,
hypertext command, or event.
..............................................................................

IMPORTANT: If your client bails out, it loses all its global variable settings.
..............................................................................

230

FDK Programmer’s Guide

Freeing system resources by bailing out

...

C r e a t i n g Yo u r C l i e n t ’ s U s e r I n t e r f a c e

The following code requests notification for the FA_Note_PreQuitDoc notification
point and then bails out after the user starts the FrameMaker product. If the user
subsequently closes a document, it displays dialog boxes indicating when the
FrameMaker product reinitializes the client and when it issues the
FA_Note_PreQuitDoc notification.
. . .
VoidT F_ApiInitialize(initialization)
IntT initialization;
{
switch (initialization){
case FA_Init_First:
/* Request notification. */
F_ApiNotification(FA_Note_PreQuitDoc, True);
/* Bail out and wait for the event. */
F_ApiBailOut();
break;
case FA_Init_Subsequent:
F_ApiAlert((StringT)"Client is reinitializing",
FF_ALERT_CONTINUE_NOTE);
break;
}
}
VoidT F_ApiNotify(notification, docId, filename)
IntT notification;
F_ObjHandleT docId;
StringT filename;
{
if (notification == FA_Note_PreQuitDoc)
F_ApiAlert((StringT)"Client has reinitialized.",
FF_ALERT_CONTINUE_NOTE);
}

FDK Programmer’s Guide 231

7

Executing Commands with API
Functions

..................................
.....

4

This chapter discusses how to use Frame API functions to execute FrameMaker product
commands programmatically.
The API doesn’t provide a function to directly execute each of the commands available
in the FrameMaker product user interface. This is because you can achieve the effect of
some commands by setting object properties. For example, to set a graphic’s fill pattern,
you set the object’s FP_Fill property. For more information on setting object
properties, see Chapter 5, “Getting and Setting Properties.”

Handling errors
When an API function fails, it stores an error code in the global variable, FA_errno.
FA_errno retains the error code until another function fails and sets it or until your
code explicitly sets it. To determine whether a set of API function calls has failed,
initialize FA_errno to FE_Success once before all the calls and check it once after
all the calls.
To find the error codes a function can generate, look up the function in Chapter 2, “FDK
Function Reference,” in the FDK Programmer’s Reference. For a list of all API error
codes and their meanings, see the fapidefs.h header file included with FDK or
Chapter 5, “Error Codes,” in the FDK Programmer’s Reference. In the interest of
brevity, the examples in this chapter do not include error-handling code. However, you
should check FA_errno after calling functions that set it.

Handling messages and warnings
In the user interface, some commands such as Open and Save sometimes need to prompt
the user with warnings or messages. The API provides two types of functions to execute
these commands:


Simple functions allow you to either suppress the messages and warnings entirely or
to prompt the user with them.



Scriptable functions allow you to specify a response for each possible message or
warning.

FDK Programmer’s Guide 233

7

Executing Commands with API Functions

Handling messages and warnings

Using simple functions
Simple functions enable you to execute commands such as Save and Open without
specifying numerous parameters. They execute these commands in either an interactive
or a noninteractive mode. If you call a simple function and specify the interactive mode,
the FrameMaker product behaves exactly as it would if the user had initiated the
command. If a message or warning condition occurs, the FrameMaker product prompts
the user. For example, if you call F_ApiSimpleOpen() in the interactive mode, the
FrameMaker product displays the Open dialog box and prompts the user to choose a file
to open. If the user chooses a text file, the FrameMaker product displays a Reading Text
File dialog box.
If you are sure that executing a command won’t do something undesirable, and you
don’t want the FrameMaker product to display error and warning messages, call a
simple function in noninteractive mode. Be careful when you do this, because you may
inadvertently destroy data. For example, suppose you attempt to save a file by calling
F_ApiSimpleSave() in the noninteractive mode. If the file already exists, the
FrameMaker product overwrites it without warning your client or the user.
Noninteractive mode is useful for clients that need to carry out tasks without a user
present.
Using scriptable functions
To specify a response for each possible message or warning that the FrameMaker
product may issue while executing a command, use a scriptable function to execute the
command. When you call a scriptable function, you pass it a script or property list that
contains properties corresponding to possible messages or warnings. For most messages
and warnings, you either specify a Yes, No, or Cancel response, or you can instruct the
FrameMaker product to prompt the user for the response. Scriptable functions return
detailed information on how the FrameMaker product executes a command. For
example, the scriptable Open function F_ApiOpen() returns information, such as
whether the file was filtered and whether an Autosave file was used.
The API provides a function named F_ApiAllocatePropVals(), which allocates a
property list that you can use with scriptable functions. The API also provides functions
that create default scripts for the different scriptable functions. You can use these
functions to get a default script and then customize the script by changing individual
properties.

234

FDK Programmer’s Guide

Opening documents and books

...

Executing Commands with API Functions

Opening documents and books
The API provides two functions to open a document or book:


F_ApiSimpleOpen() is an easy-to-use function for opening a document or book.



F_ApiOpen() allows you to script the process of opening a document or book.

Opening a document or book with F_ApiSimpleOpen()
The syntax for F_ApiSimpleOpen() is:
F_ObjHandleT F_ApiSimpleOpen(StringT fileName,
BoolT interactive);
This argument

Means

fileName

The absolute pathname of the file to open. For information on how
filenames and paths on different platforms are expressed, see the FDK
Platform Guide for your platform.

interactive

Specifies whether the FrameMaker product displays messages and warnings
to the user.

If F_ApiSimpleOpen() is successful, it returns the ID of the FO_Doc or FO_Book
object that represents the document or book that it opened. If a condition (such as a
nonexistent file) makes it impossible to open a file, F_ApiSimpleOpen() aborts the
operation and returns 0.
If you set interactive to True, the FrameMaker product displays the Open dialog
box. It uses the path specified by the session property FP_OpenDir as the default
path. The FrameMaker product also displays all the other messages and warnings it
would normally display if the user chose the Open command. For example, if a
document contains fonts that are not available in the current session, the FrameMaker
product displays a “Fonts Unavailable. Open Anyway?” dialog box. If the user clicks
Cancel, F_ApiSimpleOpen() aborts the operation and returns 0.
If you set interactive to False, the FrameMaker product does not display the
Open dialog box or other messages and warnings. If it is necessary to modify a file to
continue opening it, F_ApiSimpleOpen() aborts the operation without notifying the
user, and returns 0. For example, if a document contains fonts that are not available,
F_ApiSimpleOpen() aborts the Open operation instead of converting the fonts.

FDK Programmer’s Guide 235

7

Executing Commands with API Functions

Opening documents and books

Example
The following code opens a document named /tmp/my.doc and displays its ID:
. . .
#include "futils.h"
F_ObjHandleT docId;
UCharT msg[256];
docId = F_ApiSimpleOpen((StringT)"/tmp/my.doc", False);
if (!docId)
F_ApiAlert((StringT)"Couldn’t open.",FF_ALERT_CONTINUE_NOTE);
else
{
F_Sprintf(msg, (StringT)"my.doc’s ID is 0x%x.", docId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
}
. . .

Opening a document or book with F_ApiOpen()
To open a document or book and programmatically specify responses to warnings and
messages that the FrameMaker product issues, use F_ApiOpen(). With
F_ApiOpen(), you can specify aspects of the Open operation, such as whether to make
a document visible and whether to use an Autosave file. You can specify all aspects of
the operation, or you can specify some aspects and allow the user to decide others. For
example, you can instruct the FrameMaker product to only open a MIF file but allow the
user to choose the file.
To use F_ApiOpen(), you should first understand property lists and how to
manipulate them directly. For more information on this subject, see “Representing
object characteristics with properties” on page 63 and “Manipulating property lists
directly” on page 293.

236

FDK Programmer’s Guide

Opening documents and books

...

Executing Commands with API Functions

The syntax for F_ApiOpen() is:
F_ObjHandleT F_ApiOpen(StringT fileName,
F_PropValsT *openParamsp,
F_PropValsT **openReturnParamspp);
This argument

Means

fileName

The absolute pathname of the file to open. If you are using
F_ApiOpen() to create a document, specify the template name.

openParamsp

A property list (script) that tells the FrameMaker product how to
open the file and how to respond to errors and other conditions
that arise. Use F_ApiGetOpenDefaultParams() or
F_ApiAllocatePropVals() to create and allocate memory
for this property list. To use the default list, specify NULL.

openReturnParamspp

A property list that returns the pathname and provides
information on how the FrameMaker product opened the file.

..............................................................................

Always initialize the pointer to the property list that you specify for
openReturnParamspp to NULL before you call F_ApiOpen().
I M P O RTA NT:

..............................................................................

If F_ApiOpen() is successful, it returns the ID of the opened document or book.
Otherwise, it returns 0.
To call F_ApiOpen(), do the following:
1 Initialize the pointer to the openReturnParamspp property list to NULL.
2 Create an openParamsp property list.
You can get a default list by calling F_ApiGetOpenDefaultParams(), or you can
create a list from scratch.
3 Call F_ApiOpen().
4 Check the Open status.
Check the returned values in the openReturnParamspp list for the name of the
opened file and other information about how the FrameMaker product opened the file.

FDK Programmer’s Guide 237

7

Executing Commands with API Functions

Opening documents and books

5 Deallocate memory for the openParamsp and openReturnParamspp property
lists.
Use F_ApiDeallocatePropVals() to deallocate memory for the lists.
Steps 2, 4, and 5 are discussed in the following sections.
Creating an openParamsp script with F_ApiGetOpenDefaultParams()
If you need to specify a number of properties in the openParamsp property list, it is
easiest to get a default list with F_ApiGetOpenDefaultParams() and then modify
individual properties in the list.
The syntax for F_ApiGetOpenDefaultParams() is:
F_PropValsT F_ApiGetOpenDefaultParams();

The following table lists some of the properties in the property list returned by
F_ApiGetOpenDefaultParams(). The first value listed for each property is the
default value used in the list. You can change the list to use the other listed values. For
the complete list of properties in the property list, see “F_ApiGetOpenDefaultParams()”
on page 212 in the FDK Programmer’s Reference.
Property

Instruction or situation and possible values

FS_ShowBrowser

Display Open dialog box.
False: don’t display it.
True: display it.

FS_OpenDocViewOnly

Open document as View Only.
False: don’t open as View Only.
True: open as View Only.

FS_NameStripe

String specifying the name that appears on the document title bar.
NULL.

FS_NewDoc

Create a new document.
False: open an existing document.
True: create a new document.

238

FDK Programmer’s Guide

Opening documents and books

...

Executing Commands with API Functions

For example, to get a default openParamsp property list and modify it so that it
instructs F_ApiOpen() to show the Open dialog box, use the following code:
. . .
F_ObjHandleT docId;
F_PropValsT params, *returnParamsp = NULL;
IntT i;
/* Get a default property list. */
params = F_ApiGetOpenDefaultParams();
/* If F_ApiGetOpenDefaultParams() fails, len will be 0. */
if(params.len == 0) return;
/* Get index of FS_ShowBrowser property, then set it to True. */
i = F_ApiGetPropIndex(¶ms, FS_ShowBrowser);
params.val[i].propVal.u.ival = True;
/* Change default to /tmp when Open dialog box appears. */
F_ApiSetString(0, FV_SessionId, FP_OpenDir, "/tmp");
docId = F_ApiOpen("", ¶ms, &returnParamsp);
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API allocates memory for the property list created by
F_ApiGetOpenDefaultParams(). Use F_ApiDeallocatePropVals() to free
the property list when you are done with it.
For another example of how to call F_ApiOpen() using a default
property list created by F_ApiGetOpenDefaultParams(), see
“F_ApiGetOpenDefaultParams()” on page 212 in the FDK Programmer’s Reference.
Creating an openParamsp script from scratch
If you only need to specify a few properties when you call F_ApiOpen(), it is most
efficient to create a property list from scratch. To create the property list, you must
allocate memory for it and then set up the individual properties.

FDK Programmer’s Guide 239

7

Executing Commands with API Functions

Opening documents and books

To allocate memory for the property list, use the API convenience function,
F_ApiAllocatePropVals(). The syntax for F_ApiAllocatePropVals() is:
F_PropValsT F_ApiAllocatePropVals(IntT numProps);
This argument

Means

numProps

The number of properties for which to allocate memory

For example, the following code creates an openParamsp property list that instructs
F_ApiOpen() to show the Open dialog box:
. . .
F_ObjHandleT docId;
F_PropValsT params, *returnParamsp = NULL;
/* Allocate memory for the list. */
params = F_ApiAllocatePropVals(1);
/* Set up the FS_ShowBrowser property and set it to True. */
params.val[0].propIdent.num = FS_ShowBrowser;
params.val[0].propVal.valType = FT_Integer;
params.val[0].propVal.u.ival = True;
docId = F_ApiOpen("", ¶ms, &returnParamsp);
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API allocates memory for the property list created by
F_ApiAllocatePropVals(). Use F_ApiDeallocatePropVals() to free
the property list when you are done with it.

240

FDK Programmer’s Guide

Opening documents and books

...

Executing Commands with API Functions

Checking the Open status
F_ApiOpen() stores a pointer to a property list (F_PropValsT structure) in
openReturnParamspp. To get the name of the file that F_ApiOpen() opened and
other information about how F_ApiOpen() opened the file, check this property list.
It includes the properties shown in the following table.
Property

Meaning and possible values

FS_OpenedFileName

A string that specifies the opened file’s pathname. If you scripted
FS_ShowBrowser, or the file was filtered, or you didn’t specify
the pathname, this pathname can be different from the one you
specified in the Open script.

FS_OpenNativeError

The error condition. If the file is opened successfully, it is set to
FE_Success. For a complete list of the other values it can be set
to, see “F_ApiOpen()” on page 349 in the FDK Programmer’s
Reference.

FS_OpenStatus

A bit field indicating what happened when the file was opened.
For a complete list of the possible status flags, see
“F_ApiOpen()” on page 349 in the FDK Programmer’s
Reference.

The FS_OpenNativeError property and the FA_errno global variable indicate
the result of a call to F_ApiOpen(). The FS_OpenStatus flags indicate how or
why this result occurred. For example, if you attempt to open a file with F_ApiOpen()
and the Open operation is canceled, FS_OpenNativeError and FA_errno are set
to FE_Canceled. If the operation was canceled because the user canceled it, the
FV_UserCanceled bit of the FS_OpenStatus property list is set.
The API provides a function named F_ApiCheckStatus(), which allows you to
determine if a particular FS_OpenStatus bit is set. The syntax for
F_ApiCheckStatus() is:
IntT F_ApiCheckStatus(F_PropValsT *p,
IntT statusBit);
This argument

Means

p

The openReturnParamspp property list returned by F_ApiOpen()

statusBit

The status bit you want to test

FDK Programmer’s Guide 241

7

Executing Commands with API Functions

Opening documents and books

If the specified bit is set, F_ApiCheckStatus() returns True. For example, the
following code determines if an Open operation was canceled because a document used
unavailable fonts:
. . .
F_ObjHandleT docId;
F_PropValsT params, *returnParamsp = NULL;
/* Get default property list. */
params = F_ApiGetOpenDefaultParams();
docId = F_ApiOpen("/tmp/my.doc", ¶ms, &returnParamsp);
if (F_ApiCheckStatus(returnParamsp, FV_CancelFontsMapped))
F_ApiAlert("Canceled because my.doc has unavailable fonts.",
FF_ALERT_CONTINUE_NOTE);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API also provides a convenience function named F_ApiPrintOpenStatus(),
which prints the Open status values to the Frame console.
F_ApiPrintOpenStatus() is useful for debugging clients that use F_ApiOpen().
For more information, see “F_ApiPrintOpenStatus()” on page 364 in the FDK
Programmer’s Reference.
Deallocating Open script property lists
After you are done with the Open script property lists, call the API convenience
function, F_ApiDeallocatePropVals(), to free the memory they use.
The syntax for F_ApiDeallocatePropVals() is:
VoidT F_ApiDeallocatePropVals(F_PropValsT *pvp);

242

This argument

Means

pvp

The property list

FDK Programmer’s Guide

Opening documents and books

...

Executing Commands with API Functions

Example
The following code opens a document named /tmp/my.doc. It creates a property list
that instructs F_ApiOpen() to open the document as View Only and to display the
title, Doc, in the title bar.
. . .
#include "fstrings.h"
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT docId;
/* Allocate memory for Open script with two properties. */
params = F_ApiAllocatePropVals(2);
if(params.len == 0) return;
/* Force title displayed on title bar to be "Doc". */
params.val[0].propIdent.num = FS_NameStripe;
params.val[0].propVal.valType = FT_String;
params.val[0].propVal.u.sval = (StringT)F_StrCopyString("Doc");
/* Open the file as View Only. */
params.val[1].propIdent.num = FS_OpenDocViewOnly;
params.val[1].propVal.valType = FT_Integer;
params.val[1].propVal.u.ival = True;
/* Open /tmp/my.doc. */
docId = F_ApiOpen("/tmp/my.doc", ¶ms, &returnParamsp);
/* Free memory used by the Open scripts. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

FDK Programmer’s Guide 243

7

Executing Commands with API Functions

Creating documents

Creating documents
To create a new document, you can use the following functions:


F_ApiSimpleNewDoc() is an easy-to-use function that allows you to specify a
template and interactive or noninteractive modes.



F_ApiCustomDoc() uses the FrameMaker product’s default new document
template and some parameters that you specify to create the new document.



F_ApiOpen() allows you to script the New operation.

For information on creating books, see “Creating a book” on page 361. The following
sections describe how to create a new document in greater detail.
Creating a document with F_ApiSimpleNewDoc()
To create a new document from a specific template, use F_ApiSimpleNewDoc().
The syntax for F_ApiSimpleNewDoc() is:
F_ObjHandleT F_ApiSimpleNewDoc(StringT templateName,
IntT interactive);
This argument

Means

templateName

The absolute pathname of the template to use. For information on how
filenames and paths on different platforms are expressed, see the FDK
Platform Guide for that platform.

interactive

Specifies whether the FrameMaker product displays messages and
warnings to the user.

If you set interactive to True, the FrameMaker product creates a document from
the specified template and displays messages and warnings to the user. If you set
interactive to False, the FrameMaker product does not display messages and
warnings; if the FrameMaker product encounters a condition for which it normally
displays a dialog box, F_ApiSimpleNewDoc() attempts to do what’s necessary to
continue creating the file.
If F_ApiSimpleNewDoc() is successful, it returns the ID of the document it created;
otherwise, it returns 0. You don’t provide the name for the new document until you
save it.
..............................................................................
I M P O RTA NT: If you call F_ApiSimpleNewDoc() with interactive set to
True and the user clicks Portrait, Custom, or Landscape in the New dialog box,
F_ApiSimpleNewDoc() does not create a document. It returns 0 and sets

244

FDK Programmer’s Guide

Creating documents

...

Executing Commands with API Functions

FA_errno to FE_WantsPortrait, FE_WantsCustom, or
FE_WantsLandscape. It is up to your client to create a portrait, custom, or landscape
document by calling F_ApiCustomDoc(). For more information on creating custom
documents, see “Creating a custom document,” next.
..............................................................................

Example
The following code creates a document from the /templates/Reports/Report1
template and saves it as /tmp/mynew.doc. It then uses F_ApiSimpleSave() to
save the the document. For more information on F_ApiSimpleSave(), see “Saving
documents and books” on page 251
. . .
F_ObjHandleT docId;
docId = F_ApiSimpleNewDoc("/templates/Reports/Report1", False);
if (!docId)
F_ApiAlert("Can’t create document.", FF_ALERT_CONTINUE_NOTE);
else
F_ApiSimpleSave(docId, "/tmp/mynew.doc", False);
. . .

Creating a custom document
To create a custom new document, use F_ApiCustomDoc(). This function uses the
FrameMaker product’s default new-document template to create the custom document.
For more information on the default new-document template, see “Documents” on
page 73.
The syntax for F_ApiCustomDoc() is:
F_ObjHandleT F_ApiCustomDoc(MetricT width,
MetricT height,
IntT numCols,
MetricT columnGap,
MetricT topMargin,
MetricT botMargin,
MetricT leftinsideMargin,
MetricT rightoutsideMargin,
IntT sidedness,
BoolT makeVisible);

FDK Programmer’s Guide 245

7

Executing Commands with API Functions

Creating documents

This argument

Means

width

Page width. The Frame API expresses linear measurements with
MetricT values. For more information on MetricT values, see
Chapter 4, “Data Types and Structures Reference,” in the FDK
Programmer’s Reference.

height

Page height.

numCols

Default number of columns.

columnGap

Default column spacing.

topMargin

Page top margin.

botMargin

Page bottom margin.

leftinsideMargin

Left margin (for single-sided documents) or the inside margin
(for double-sided documents).

rightoutsideMargin

Right margin (for single-sided documents) or the outside margin
(for double-sided documents).

sidedness

Constant that specifies whether the document is single-sided or
double-sided and on which side the document starts. See the
following table for the list of constants.

makeVisible

Specifies whether to make the document visible. True makes it
visible.

The sidedness argument can have any of the values shown in the following table.
sidedness constant

New document page characteristics

FF_Custom_SingleSided

Single-sided

FF_Custom_FirstPageRight

Double-sided, starting with a right page

FF_Custom_FirstPageLeft

Double-sided, starting with a left page

If successful, F_ApiCustomDoc() returns the ID of the document it created.
Otherwise, it returns 0.

246

FDK Programmer’s Guide

Creating documents

...

Executing Commands with API Functions

Example
The following code creates a custom document with the characteristics specified in the
dialog box in Figure 4-1:
. . .
#include "fmetrics.h"
#define in (MetricT)(65536*72) /* A Frame metric inch */
F_ObjHandleT docId;
docId = F_ApiCustomDoc(F_MetricFractMul(in,17,2), 11*in, 1,
F_MetricFractMul(in,1,4), in, in, in, in,
FF_Custom_SingleSided, True);
. . .

Figure 4-1 Specifications for custom document

Creating a document with F_ApiOpen()
To create a document with F_ApiOpen(), set the FS_NewDoc property in the
openParamsp script to True. For the syntax of F_ApiOpen(), see “Opening a
document or book with F_ApiOpen()” on page 236.
When you use F_ApiOpen() to create a document, set fileName to the name of
the template that you want to use. You don’t provide the name for the new document
until you save it.

FDK Programmer’s Guide 247

7

Executing Commands with API Functions

Creating documents

For example, the following code creates a document from a template named
/tmp/template and saves it as /tmp/mynew.doc.
. . .
F_ObjHandleT docId;
F_PropValsT params, *returnParamsp = NULL;
params = F_ApiAllocatePropVals(1);
if(params.len == 0) return;
/* Set up the FS_NewDoc property and set it to True. */
params.val[0].propIdent.num = FS_NewDoc;
params.val[0].propVal.valType = FT_Integer;
params.val[0].propVal.u.ival = True;
docId = F_ApiOpen("/tmp/template", ¶ms, &returnParamsp);
/* See “Saving documents and books” on page 251 for syntax. */
F_ApiSimpleSave(docId, "/tmp/mynew.doc", False);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .
..............................................................................

If you are creating a document with F_ApiOpen() and you display
the New dialog box (by setting FS_ShowBrowser to True), the user may click
Portrait, Custom, or Landscape. If this occurs, F_ApiOpen() does not create a new
document. It returns 0 and sets FA_errno to FE_WantsPortrait,
FE_WantsCustom, or FE_WantsLandscape. It is up to your client to create a
portrait, custom, or landscape document by calling F_ApiCustomDoc().
I M P O RTA NT:

..............................................................................

248

FDK Programmer’s Guide

Printing documents and books

...

Executing Commands with API Functions

Printing documents and books
To print a document or book, use F_ApiSilentPrintDoc().
F_ApiSilentPrintDoc() uses the default print settings for a document. The default
print settings are the settings that appear in the Print dialog box when the user attempts
to print the document in the user interface.
The syntax for F_ApiSilentPrintDoc() is:
IntT F_ApiSilentPrintDoc(F_ObjHandleT docId);
This argument

Means

docId

The ID of the document or book to print

When you call F_ApiSilentPrintDoc(), the FrameMaker product doesn’t notify
the user about error or warning conditions that occur when it attempts to print. To
determine whether an error occurred, check FA_errno.
Changing the print settings for a document
When you print a document in the user interface, you can change the
print settings in the Print dialog box. FrameMaker products save most print settings with
a document. For example, if you set the scale to 90 percent and print the document in
the same session or save the document, the default setting for the scale will be
90 percent. Similarly, if an API client calls F_ApiSilentPrintDoc() to print the
document, the scale will be 90 percent, if the client doesn’t change it.
The API represents a document’s print settings with a set of document properties. For
example, a document’s FP_PrintNumCopies property specifies the number of
copies of the document to print. To change a print setting programmatically, you change
the property that represents it. For more information on changing properties, see
Chapter 5, “Getting and Setting Properties.” For a list of document print properties, see
“Document print properties” on page 806 in the FDK Programmer’s Reference.
Examples
The following code opens a document named /tmp/my.doc and prints it using the
default print settings:
. . .
F_ObjHandleT docId;
docId = F_ApiSimpleOpen("/tmp/my.doc", False);
F_ApiSilentPrintDoc(docId);
. . .

FDK Programmer’s Guide 249

7

Executing Commands with API Functions

Printing documents and books

The following code opens /tmp/my.doc and modifies its default print settings so that
the FrameMaker product will print two copies of the document to a printer named ps2.
It does this by setting the document properties that specify the number of copies
(FP_PrintNumCopies) and the printer (FP_PrinterName) to 2 and ps2,
respectively:
. . .
F_ObjHandleT docId;
/* Open the document. */
docId = F_ApiSimpleOpen("/tmp/my.doc", False);
/* Change my.doc’s print properties. */
F_ApiSetInt(FV_SessionId, docId, FP_PrintNumCopies, 2);
F_ApiSetString(FV_SessionId, docId, FP_PrinterName, "ps2");
F_ApiSilentPrintDoc(docId);
. . .

If you save /tmp/my.doc or attempt to print it within the same session, the default
printer will be ps2 and the default number of copies will be 2 unless your client or the
user changes the values of FP_PrinterName and FP_PrintNumCopies.

250

FDK Programmer’s Guide

Saving documents and books

...

Executing Commands with API Functions

Saving documents and books
To save a document or book, use one of the following functions:


F_ApiSimpleSave() is an easy-to-use function for saving a document or book.



F_ApiSave() allows you to script the process for saving a document or book.

Saving a document or book with F_ApiSimpleSave()
The syntax for F_ApiSimpleSave() is:
F_ObjHandleT F_ApiSimpleSave(F_ObjHandleT docId,
StringT saveAsName,
IntT interactive);
This argument

Means

docId

ID of the document or book to save.

saveAsName

Name of the pathname to save the document or book to. For information on
how filenames and paths on different platforms are represented, see the
FDK Platform Guide for that platform.

interactive

Specifies whether the FrameMaker product displays messages and
warnings to the user (True to display messages and warnings).

If you set interactive to False and you specify the document or book’s current
name, the FrameMaker product saves the document or book under its current name. If
you specify another filename for saveAsName, the FrameMaker product saves the
document or book to that filename.
If you set interactive to True, the FrameMaker product displays the Save dialog
box and allows the user to choose a filename. The document or book’s current name
appears as the default name.
If F_ApiSimpleSave() is successful, it returns the ID of the document it saved. If
you save the document under its current name, the returned ID is the same ID you
specified in the docId parameter. If you specify another filename for saveAsName,
the returned ID is the ID of the new document. If F_ApiSimpleSave() can’t save
the file, it returns 0.

FDK Programmer’s Guide 251

7

Executing Commands with API Functions

Saving documents and books

Example
The following code opens and then saves a document named /tmp/my.doc. After it
has saved the document as /tmp/my.doc, it saves a copy of it as mynew.doc:
. . .
#include "futils.h"
F_ObjHandleT mydocId, mynewdocId;
UCharT msg[256];
mydocId = F_ApiSimpleOpen("/tmp/my.doc", False);
/* Save my.doc as itself. */
F_ApiSimpleSave(mydocId, "/tmp/my.doc", False);
/* Save my.doc as mynew.doc. */
mynewdocId = F_ApiSimpleSave(mydocId, "/tmp/mynew.doc", False);
/* If the Save As was successful, display ID of mynew.doc. */
if (!mynewdocId)
F_ApiAlert("Couldn’t save as mynew.doc.",
FF_ALERT_CONTINUE_NOTE);
else {
F_Sprintf(msg, "The ID of mynew.doc is 0x%x.", mynewdocId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
}
. . .

Saving a document or book with F_ApiSave()
To save a document or book and specify responses to warnings and messages that the
FrameMaker product issues, use the scriptable save function, F_ApiSave(). With
F_ApiSave(), you can specify aspects of the Save operation, such as the file format
(for example, MIF or Text Only). You can specify all aspects, or you can specify some
and allow the user to decide others. For example, you can specify that the FrameMaker
product should save a document as Text Only, but allow the user to decide how to
convert the document’s tables to text.

252

FDK Programmer’s Guide

Saving documents and books

...

Executing Commands with API Functions

The syntax for F_ApiSave() is:
F_ObjHandleT F_ApiSave(F_ObjHandleT docId,
StringT saveAsName,
F_PropValsT *saveParamsp,
F_PropValsT **saveReturnParamspp);
This argument

Means

docId

The ID of the document or book to save.

saveAsName

The pathname to save the document or book to.

saveParamsp

A property list that tells the FrameMaker product how to save the
file and how to respond to errors and other conditions. Use
F_ApiGetSaveDefaultParams() or
F_ApiAllocatePropVals() to create and allocate memory
for this property list. To use the default list, specify NULL.

saveReturnParamspp

A property list that returns information about how the
FrameMaker product saved the file.

..............................................................................

Always initialize the pointer to the property list that you specify for
saveReturnParamspp to NULL before you call F_ApiSave().
I M P O RTA NT:

..............................................................................

If F_ApiSave() is successful, it returns the ID of the document or book it saved. If
F_ApiSave() performs a Save operation, it returns the ID that you specified in the
docId parameter. If F_ApiSave() performs a Save As operation, it returns the ID
of the new document or book. If F_ApiSave() can’t save a file, it returns 0.
To call F_ApiSave(), do the following:
1 Initialize the pointer to the saveReturnParamspp property list to NULL.
2 Create a saveParamsp property list.
You can get a default list by calling F_ApiGetSaveDefaultParams(), or you can
create a list from scratch.
3 Call F_ApiSave().
4 Check the Save status.
Check the returned values in the saveReturnParamspp list for the name of the
saved file and other information about how the FrameMaker product saved the file.
5 Deallocate the saveParamsp and saveReturnParamspp property lists.
Steps 2, 4, and 5 are discussed in the following sections.

FDK Programmer’s Guide 253

7

Executing Commands with API Functions

Saving documents and books

Creating a saveParamsp script with F_ApiGetSaveDefaultParams()
The API provides a function named F_ApiGetSaveDefaultParams() that creates
a default saveParamsp property list. If you are setting a number of properties, it is
easiest to use F_ApiGetSaveDefaultParams() to get a default property list and
then change individual properties as needed.
The syntax for F_ApiGetSaveDefaultParams() is:
F_PropValsT F_ApiGetSaveDefaultParams();

The following table lists some of the properties in the property list returned by
F_ApiGetSaveDefaultParams(). The first value listed for each property is the
default value returned by F_ApiGetSaveDefaultParams(). You can change the
list to use the other listed values.
Property

Meaning and possible values

FS_FileType

Specifies the type of file to save to
FV_SaveFmtBinary: save in Frame binary format
FV_SaveFmtInterchange: save as MIF
FV_SaveFmtStationery: save in Stationery format
FV_SaveFmtViewOnly: save as View Only
FV_SaveFmtText: save as Text Only
FV_SaveFmtSgml: save as SGML
FV_SaveFmtPdf: save as PDF

FS_AlertUserAboutFailure

Specifies whether to notify the user if something unusual
occurs while the file is being saved
False: don’t notify user
True: notify user

FS_SaveMode

Specifies whether to use Save or Save As mode
FV_ModeSaveAs: use Save As mode
FV_ModeSave: use Save mode

For the complete property list returned by F_ApiGetSaveDefaultParams(), see
“F_ApiGetSaveDefaultParams()” on page 227 in the FDK Programmer’s Reference.

254

FDK Programmer’s Guide

Saving documents and books

...

Executing Commands with API Functions

For example, to get a default saveParamsp property list and modify it so that it
instructs F_ApiSave() to save the active document as Text Only, use the following
code:
. . .
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT mydocId;
IntT i;
/* Get the ID of the active document. */
mydocId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get default property list. */
params = F_ApiGetSaveDefaultParams();
/* Get index of FS_FileType property and set it to Text Only. */
i = F_ApiGetPropIndex(¶ms, FS_FileType);
params.val[i].propVal.u.ival = FV_SaveFmtText;
/* Save to text only file named my.txt. */
F_ApiSave(mydocId, "/tmp/my.txt", ¶ms, &returnParamsp);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API allocates memory for the property list created by
F_ApiGetSaveDefaultParams(). Use F_ApiDeallocatePropVals() to free
the property list when you are done with it.
Creating a saveParamsp script from scratch
If you want to specify only a few properties when you call F_ApiSave(), it is most
efficient to create a property list from scratch. To create the property list, you must
allocate memory for it, and then set up the individual properties.

FDK Programmer’s Guide 255

7

Executing Commands with API Functions

Saving documents and books

Use the API convenience function, F_ApiAllocatePropVals(), to allocate
memory for the property list. For example, the following code creates a saveParamsp
property list that instructs F_ApiSave() to save a file as text only:
. . .
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT mydocId;
/* Get the ID of the active document. */
mydocId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Allocate memory for the list. */
params = F_ApiAllocatePropVals(1);
/* Set up the FS_FileType property and set it to True. */
params.val[0].propIdent.num = FS_FileType;
params.val[0].propVal.valType = FT_Integer;
params.val[0].propVal.u.ival = FV_SaveFmtText;
F_ApiSave(mydocId, "/tmp/my.txt", ¶ms, &returnParamsp);
. . .

Checking Save status
F_ApiSave() stores a pointer to a property list in saveReturnParamspp. This
property list provides information on how the FrameMaker product saved the file. It
includes the properties shown in the following table.
Property

Meaning and Possible Values

FS_SavedFileName

A string that specifies the saved file’s pathname.

FS_SaveNativeError

The error condition. If the file is saved successfully, it is set to
FE_Success. For a complete list of the other values it can be set
to, see “F_ApiSave()” on page 393 in the FDK Programmer’s
Reference.

FS_SaveStatus

A bit field indicating what happened when the file was saved. For
a complete list of the possible status flags, see “F_ApiSave()” on
page 393 in the FDK Programmer’s Reference.

The FS_SaveNativeError property and the FA_errno value indicate the result
of the call to F_ApiSave(). The FS_SaveStatus flags indicate how or why this
result occurred.
To determine if a particular FS_SaveStatus bit is set, use F_ApiCheckStatus().

256

FDK Programmer’s Guide

Saving documents and books

...

Executing Commands with API Functions

Example
The following code opens /tmp/my.doc and saves it as a View Only document
named /tmp/viewonly.doc. It gets the name of the saved file from the returned
property list and displays it.
. . .
#include "futils.h"
IntT i;
UCharT msg[1024];
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT mydocId, viewonlydocId;
params = F_ApiAllocatePropVals(1);
mydocId = F_ApiSimpleOpen("/tmp/my.doc", False);
if(!mydocId) return;
/* Set file type to View Only. */
params.val[0].propIdent.num = FS_FileType;
params.val[0].propVal.valType = FT_Integer;
params.val[0].propVal.u.ival = FV_SaveFmtViewOnly;
/* Save document as viewonly.doc. */
viewonlydocId = F_ApiSave(mydocId, "/tmp/viewonly.doc",
¶ms, &returnParamsp);
/* Get index of property specifying filename and display it. */
i = F_ApiGetPropIndex(returnParamsp, FS_SavedFileName);
F_Sprintf(msg, "Saved: %s",
returnParamsp->val[i].propVal.u.sval);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
/* Deallocate Save scripts. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

FDK Programmer’s Guide 257

7

Executing Commands with API Functions

Closing documents and books

Closing documents and books
To close a document or book, use F_ApiClose().
The syntax for F_ApiClose() is:
IntT F_ApiClose(F_ObjHandleT Id,
IntT flags);
This argument

Means

Id

The ID of the document, book, or session to close. To close the session,
specify FV_SessionId.

flags

Specifies whether to abort or to close open documents or books if they have
unsaved changes. Set the FF_CLOSE_MODIFIED flag to close open
documents and books regardless of their state.

F_ApiClose() behaves somewhat differently than the Close command in the user
interface. If there are unsaved changes in a file and you set FF_CLOSE_MODIFIED for
the flags argument, F_ApiClose() abandons the changes and closes the file
anyway. If you set flags to 0, F_ApiClose() aborts the Close operation and
returns FE_DocModified.
..............................................................................

If you are closing an individual document, make sure Id specifies a
valid document ID and not 0. If Id is set to 0, F_ApiClose() quits the Frame
session (because FV_SessionId is defined as 0).
I M P O RTA NT:

..............................................................................

258

FDK Programmer’s Guide

Closing documents and books

...

Executing Commands with API Functions

Examples
The following code closes the active document. If the document has unsaved changes,
the client prompts the user.
. . .
F_ObjHandleT docId;
IntT resp = 0;
/* Get the ID of active document. Return if there isn’t one. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if(!docId) return;
/* See if document has been modified. */
if (F_ApiGetInt(FV_SessionId, docId, FP_DocIsModified))
resp = F_ApiAlert("Document was changed, close it anyway?",
FF_ALERT_OK_DEFAULT);
if (!resp) F_ApiClose(docId, FF_CLOSE_MODIFIED);
. . .

The following code closes the active document unless it has unsaved changes:
. . .
F_ObjHandleT docId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if(!docId) return;
if (F_ApiClose(docId, 0))
F_ApiAlert("Unsaved changes. Can’t close.",
FF_ALERT_CONTINUE_WARN);
. . .

FDK Programmer’s Guide 259

7

Executing Commands with API Functions

Quitting a Frame session

Quitting a Frame session
To quit a Frame session, call F_ApiClose(), with Id set to FV_SessionId. For
the syntax of F_ApiClose(), see “Closing documents and books” on page 258.
For example, to close all the open documents and books in the current Frame session,
and quit the session, use the following code:
. . .
F_ApiClose(FV_SessionId, FF_CLOSE_MODIFIED);
. . .

Becaus of the flag set to FF_CLOSE_MODIFIED, if any books or documents have been
changed, the FrameMaker product abandons the changes.

Comparing documents and books
To compare two versions of a document or book using a FrameMaker product’s built-in
comparison feature, use F_ApiCompare().
The syntax for F_ApiCompare() is:
F_CompareRetT F_ApiCompare(F_ObjHandleT olderId,
F_ObjHandleT newerId,
IntT flags,
StringT insertCondTag,
StringT deleteCondTag,
StringT replaceText,
IntT compareThreshold);

260

This argument

Means

olderId

The ID of the older version of the document or book.

newerId

The ID of the newer version of the document or book.

flags

Bit flags that specify how to generate the summary and composite
documents.

insertCondTag

The condition tag to apply to insertions shown in the composite
document. For no insert condition tag, specify NULL.

deleteCondTag

The condition tag to apply to deletions shown in the composite
document. For no delete condition tag, specify NULL.

FDK Programmer’s Guide

Comparing documents and books

...

Executing Commands with API Functions

This argument

Means

replaceText

Text to appear in place of the deleted text. For no replacement text,
specify NULL.

compareThreshold

Percentage of words that can change before paragraphs are
considered not equal. If two paragraphs are equal, word differences
between them are shown within a paragraph in the composite
document. If a paragraph is not equal to another, it is marked
inserted or deleted. To specify an 85% threshold, set
compareThreshold to 85. The default value is 75.

The F_CompareRetT structure is defined as:
typedef struct {
F_ObjHandleT sumId; /* ID of the summary document */
F_ObjHandleT compId; /* ID of the composite document */
} F_CompareRetT;

The following values can be ORed into the flags argument.
This value

Means

FF_CMP_SUMMARY_ONLY

Generate summary document, but not composite document

FF_CMP_CHANGE_BARS

Turn on change bars in the composite document

FF_CMP_HYPERLINKS

Put hypertext links in the summary document

FF_CMP_SUMKIT

Open the summary document

FF_CMP_COMPKIT

Open the composite document

If you specify the FF_CMP_SUMKIT or FF_CMP_COMPKIT flags,
F_ApiCompare() opens the summary and comparison documents and returns their
IDs in the F_CompareRetT structure. It does not make these documents visible to the
user. If you want them to be visible, you must set each of the document’s
FP_DocIsOnScreen properties to True.

FDK Programmer’s Guide 261

7

Executing Commands with API Functions

Comparing documents and books

Example
The following code opens two documents and compares them as specified in the dialog
boxes shown in Figure 4-2. It makes the summary document visible.
. . .
F_ObjHandleT oldId, newId;
IntT flags;
F_CompareRetT cmp;
oldId = F_ApiSimpleOpen("/tmp/1Chapter", False);
newId = F_ApiSimpleOpen("/tmp/1Chapter.new", False);
flags = FF_CMP_CHANGE_BARS | FF_CMP_COMPKIT | FF_CMP_SUMKIT;
cmp = F_ApiCompare(oldId, newId, flags, "Comment",
"", "Replaced Text", 75);
if (FA_errno != FE_Success)
F_ApiAlert("Couldn’t compare", FF_ALERT_CONTINUE_NOTE);
. . .

Figure 4-2 Specifications for Compare Documents

262

FDK Programmer’s Guide

Updating and generating documents and books

...

Executing Commands with API Functions

Updating and generating documents and books
The API provides a variety of functions that allow you to generate, update, and reformat
documents and books. The following sections discuss these functions.
Updating the files in a book
To update the numbering, text insets, cross-references, etc. in all the files in a book, and
to programmatically specify responses to warnings and messages that the FrameMaker
product issues, use F_ApiUpdateBook(). You can specify all aspects of the
operation, or you can specify some aspects and allow the user to decide others. For
example, you can instruct the FrameMaker product to update view-only files, or to abort
the update when it encounters a view-only file.
To use F_ApiUpdateBook(), you should first understand property lists and how to
manipulate them directly. For more information on this subject, see “Representing
object characteristics with properties” on page 63 and “Manipulating property lists
directly” on page 293.
The syntax for F_ApiUpdateBook() is:
ErrorT F_ApiOpen(F_ObjHandleT bookId,
F_PropValsT *updateParamsp,
F_PropValsT **updateReturnParamspp);
This argument

Means

bookId

The ID of the book you will update.

updateParamsp

A property list (script) that tells the FrameMaker product how
to update the book and how to respond to errors and other
conditions that arise. Use
F_ApiGetUpdateBookDefaultParams() or
F_ApiAllocatePropVals() to create and allocate
memory for this property list. To use the default list, specify
NULL.

updateReturnParamspp

A property list that provides information on how the
FrameMaker product updated the book.

..............................................................................

Always initialize the pointer to the property list that you specify for
openReturnParamspp to NULL before you call F_ApiUpdateBook().
I M P O RTA NT:

..............................................................................

If F_ApiUpdateBook() is successful, it returns FE_Success. Otherwise, it returns
an error which has the same value as FA_errno.

FDK Programmer’s Guide 263

7

Executing Commands with API Functions

Updating and generating documents and books

To call F_ApiUpdateBook(), do the following:
1 Initialize the pointer to the updateReturnParamspp property list to NULL.
2 Create an updateParamsp property list.
You can get a default list by calling F_ApiGetUpdateBookDefaultParams(), or
you can create a list from scratch.
3 Call F_ApiUpdateBook().
4 Check the Update status.
Check the returned values in the updateReturnParamspp list for the name of the
opened file and other information about how the FrameMaker product opened the file.
5 Deallocate memory for the updateParamsp and updateReturnParamspp
property lists.
Use F_ApiDeallocatePropVals() to deallocate memory for the lists.
Generating files for a book
To generate and update files for a book, use F_ApiSimpleGenerate().
The book and its generated files must be set up before you call
F_ApiSimpleGenerate().
The syntax for F_ApiSimpleGenerate() is:
IntT F_ApiSimpleGenerate(F_ObjHandleT bookId,
IntT interactive,
IntT makeVisible);
This argument

Means

bookId

The ID of the book for which to generate files

interactive

Specifies whether to display warnings and messages to the user (True
displays messages and warnings)

makeVisible

Specifies whether to display generated files (True displays the files)

Importing formats
To import formats from a document to all the documents in a book or from one
document to another document, use F_ApiSimpleImportFormats().

264

FDK Programmer’s Guide

Updating and generating documents and books

...

Executing Commands with API Functions

The syntax for F_ApiSimpleImportFormats() is:
IntT F_ApiSimpleImportFormats(F_ObjHandleT bookId,
F_ObjHandleT fromDocId,
IntT formatFlags);
This argument

Means

bookId

The ID of the book or document to which to import formats

fromDocId

The ID of the document from which to import formats

formatFlags

Bit field that specifies the formats to import

You can OR the values in the following table into the formatFlags parameter to
specify which formats to import.
This value

Means

FF_UFF_COLOR

Import colors

FF_UFF_COMBINED_FONTS

Import combined font definitions

FF_UFF_COND

Import conditional text settings

FF_UFF_DOCUMENT_PROPS

Import document properties

FF_UFF_FONT

Import Character Catalog formats

FF_UFF_MATH

Import equation settings

FF_UFF_PAGE

Import page layouts

FF_UFF_PGF

Import Paragraph Catalog formats

FF_UFF_REFPAGE

Import reference pages

FF_UFF_TABLE

Import Table Catalog formats

FF_UFF_VAR

Import variable formats

FF_UFF_XREF

Import cross-reference formats

FF_UFF_REMOVE_EXCEPTIONS

Remove exception formats from target documents

FF_UFF_REMOVE_PAGE_BREAKS

Remove all forced page breaks from target documents

Executing other updating and formatting commands
The API provides several functions that allow you to execute FrameMaker product
commands that update and reformat entire documents.

FDK Programmer’s Guide 265

7

Executing Commands with API Functions

Updating and generating documents and books

The syntax for the functions is:
IntT
IntT
IntT
IntT
IntT
IntT
IntT

F_ApiClearAllChangebars(F_ObjHandleT docId);
F_ApiRehyphenate(F_ObjHandleT docId);
F_ApiResetReferenceFrames(F_ObjHandleT docId);
F_ApiResetEqnSettings(F_ObjHandleT docId);
F_ApiRestartPgfNumbering(F_ObjHandleT docId);
F_ApiUpdateVariables(F_ObjHandleT docId);
F_ApiUpdateXRefs(F_ObjHandleT docId,
IntT updateXRefFlags);

This argument

Means

docId

ID of the document to update or reformat

These functions behave like the corresponding commands in the user interface. They are
useful for clients that need to update and reformat multiple files. For more information
on a particular function, look it up in Chapter 2, “FDK Function Reference,” in the FDK
Programmer’s Reference.

266

FDK Programmer’s Guide

Updating and generating documents and books

...

Executing Commands with API Functions

Example
The following code opens a book and resets the change bars in each of its component
documents:
. . .
#include "fmemory.h"
F_ObjHandleT bookId, compId, docId;
StringT compName;
bookId = F_ApiSimpleOpen("/tmp/my.book", False);
compId = F_ApiGetId(FV_SessionId, bookId,
FP_FirstComponentInBook);
/* Traverse book’s components, opening each one
* and clearing its change bars.
*/
while(compId)
{
compName = F_ApiGetString(bookId, compId, FP_Name);
docId = F_ApiSimpleOpen(compName, False);
F_Free(compName);
F_ApiClearAllChangebars(docId);
compId = F_ApiGetId(bookId, compId, FP_NextComponentInBook);
}
. . .

Controlling Undo/Redo in the FDK API
Undo/Redo in FrameMaker is controlled by the following:


Initialization Flag



Session Properties



API Functions

Initialization Flag to explicitly enable or disable undo/redo
The EnableUndoInFDK flag in the initialization file (maker.ini) allows you to explicitly
enable or disable undo/redo functionality for API commands, and its associated
overhead. It is false (off) by default, which means that the undo behavior is the same as
in previous releases; that is, calls to API commands clear the undo and redo stacks in the
selected document, and API commands cannot be undone. To enable the new undo
behavior for API commands, set the flag to true. (This flag does not affect the
FrameMaker user interface or interactive behavior.)
FDK Programmer’s Guide 267

7

Executing Commands with API Functions

Updating and generating documents and books

When EnableUndoInFDK is true, all API commands that modify document contents
can be undone (see “Undoable API Commands” on page 268). Commands that do not
modify content, such as saving a document, copying text, or manipulating windows,
cannot be undone and are not recorded in the command history (undo stack).
Session Properties to Control Undo/Redo
FP_UndoFDKRecording - This property, can override the default value specified in
the initialization flag EnableUndoInFDK. Use F_ApiSetInt to set this property value,
and F_ApiGetInt to retrieve it. Set the property to zero to disable FDK Undo recording
for a session, or to a non-zero value to enable Undo recording.
FP_StackWarningLevel - This property determines how warnings are displayed
when history-clearing operations occur. It corresponds to an option set in the
Preferences dialog, and to the preference-file flag hpWarning. Use F_ApiSetInt to set
this property value, and F_ApiGetInt to retrieve it. Allowed values are:


FvWarnNever: Disables warnings for history-clearing operations for the session.



FvWarnOnce: Displays a warning when a particular history-clearing command is
issued,but does not warn on subsequent uses of that command.



FvWarnAlways: Displays warnings every time a history-clearing command is
issued.

API Functions to Control Undo/Redo
The F_ApiUndoCancel command explicitly clears both the undo and redo stacks in a
specified document. The other individual API commands do not clear the undo stack
Many API commands call two or more other API functions. By default, each API call is
recorded as a separate undo action in the undo stack of the selected document. To treat
a series of API calls as one command, call F_ApiUndoStartCheckpoint before the
first call and F_ApiUndoEndCheckpoint after the last call in the group.
Undoable API Commands
The following API commands are undoable

268

F_ApiAddCols

F_ApiAddRows

F_ApiAddText

F_ApiApplyPageLayout

F_ApiClear

ApiClearAllChangebars

F_ApiCut

F_ApiDelete

F_ApiDeleteCols

F_ApiDeletePropByName

F_ApiDeleteRows

F_ApiDeleteText

FDK Programmer’s Guide

Updating and generating documents and books

...

Executing Commands with API Functions

F_ApiDeleteTextInsetContents

F_ApiDeleteUndefinedAttributes

F_ApiDemoteElement

F_ApiImport

F_ApiMergeIntoFirst

F_ApiMergeIntoLast

F_ApiNewAnchoredFormattedObject

F_ApiNewAnchoredObject

F_ApiNewBookComponentInHierarchy F_ApiNewElement
F_ApiNewElementInHierarchy

F_ApiNewGraphicObject

F_ApiNewNamedObject

F_ApiNewSeriesObject

F_ApiNewSubObject

F_ApiNewTable

F_ApiPaste

F_ApiPromoteElement

F_ApiReformat

F_ApiUnStraddleCells

F_ApiResetEqnSettings

F_ApiResetReferenceFrames

F_ApiRestartPgfNumbering

F_ApiSetAttributeDefs

F_ApiSetAttributes

F_ApiSetElementRange

F_ApiSetId

F_ApiSetInt

F_ApiSetIntByName

F_ApiSetInts

F_ApiSetMetric

F_ApiSetMetricByName

F_ApiSetMetrics

F_ApiSetPoints

F_ApiSetProps

F_ApiSetPropVal

F_ApiSetString

F_ApiSetStrings

F_ApiSetTabs

F_ApiSetTextLoc

F_ApiSetTextProps

F_ApiSetTextPropVal

F_ApiSetTextRange

F_ApiSetTextVal

F_ApiSetUBytesByName

F_ApiUnWrapElement

F_ApiSimpleImportElementDefs

F_ApiSimpleImportFormats

F_ApiSplitElement

F_ApiStraddleCells

F_ApiUnWrapElement

F_ApiUpdateTextInset

F_ApiSave

F_ApiSimpleSave

FDK Programmer’s Guide 269

7

Executing Commands with API Functions

Simulating user input

Simulating user input
To simulate user input, call the API function F_ApiFcodes().
F_ApiFcodes() sends an array of function codes (f-codes) to the FrameMaker
product. F-codes are hexadecimal codes that specify individual user actions, such as
cursor movement and text entry. They are especially useful for manipulating windows.
For example, the f-code KBD_EXPOSEWIN brings the active document or book
window to the front. When you use F_ApiFcodes() to send an array of f-codes to a
FrameMaker product, it executes each f-code as if the user performed the action.
..............................................................................
I M P O RTA NT: F_ApiFcodes() does not work with dialog boxes on Windows.
..............................................................................

The syntax for F_ApiFcodes() is:
IntT F_ApiFcodes(IntT len,
IntT *vec);
This argument

Means

len

The length of the array of f-codes in bytes

vec

The array of f-codes to send to the FrameMaker product

The following table lists some user actions and the f-codes that emulate them.
User action

F-code

Move insertion point to first flow on the current page

CSR_TOP

Move insertion point to the start of the next word

CSR_NEXT_BOW

Move insertion point to the beginning of the next paragraph

CSR_NEXT_BOP

Center the current paragraph

PGF_CENTER

Left justify the current paragraph

PGF_LEFT

Make selected text bold

TXT_BOLD

For a complete list of f-codes, see the fcodes.h file shipped with the FDK.
F_ApiFcodes() uses the current focus in a dialog box or a visible document. If you
want to execute a set of f-codes in a particular dialog box or document, make sure that
the dialog box or document is active. To make a dialog box active, use f-codes such as

270

FDK Programmer’s Guide

Straddling table cells

...

Executing Commands with API Functions

FOCUS_INPUT_SEARCH and FOCUS_INPUT_PGFFMT. To make a document active,
set the session property FP_ActiveDoc to the document’s ID.
Many f-codes perform tasks that API functions also perform. Whenever possible, try to
use the other API functions instead of F_ApiFcodes() to perform these tasks.
F_ApiFcodes() does not provide error or status feedback for individual f-codes,
whereas each API function stores an error code to FA_errno when it fails. It is also
difficult to debug lengthy f-code sequences.
The following code uses f-codes to enter the string HI!, select the text, and then make
it bold:
. . .
static IntT fcodes[] = {CSR_TOP,'H','I','!',HIGH_WORD_PREV,
TXT_BOLD};
F_ApiFcodes(sizeof(fcodes)/sizeof(IntT), fcodes);
. . .

Straddling table cells
To straddle and unstraddle table cells, use F_ApiStraddleCells() and
F_ApiUnStraddleCells().
The syntax for these functions is:
IntT F_ApiStraddleCells(F_ObjHandleT docId,
F_ObjHandleT cellId,
IntT heightInRows,
IntT widthInCols);
IntT F_ApiUnStraddleCells(F_ObjHandleT docId,
F_ObjHandleT cellId,
IntT heightInRows,
IntT widthInCols);
This argument

Means

docId

The ID of the document containing the table

cellId

The ID of the first (leftmost and uppermost) cell to straddle or unstraddle

heightInRows

The number of cells to straddle or unstraddle vertically

widthInCols

The number of cells to straddle or unstraddle horizontally

Both heightInRows and widthInCols must be greater than 0. At least one of
them must be greater than 1. The cells you straddle must all be from the same type of
row. You can’t, for example, straddle a set of cells that are in both heading and body
FDK Programmer’s Guide 271

7

Executing Commands with API Functions

Executing FrameMaker commands

rows. You also can’t straddle cells that are already straddled. If the cells you specify
include cells that are already straddled, F_ApiStraddleCells() returns
FE_BadOperation.
When you or the user straddle table cells, the FrameMaker product does not delete any
of the FO_Cell objects that represent the cells. It links the paragraphs from the
straddled cells into a single list. The FP_FirstPgf and FP_LastPgf properties of
each cell in the straddle specify the first and last paragraphs in this list.
Example
The following code straddles the first two cells in the first column of a table:
. . .
F_ObjHandleT docId, tableId, firstrowId, cellId;
/* Get IDs of document, table, first row, and first cell. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tableId = F_ApiGetId(FV_SessionId, docId, FP_FirstTblInDoc);
firstrowId = F_ApiGetId(docId, tableId, FP_FirstRowInTbl);
cellId = F_ApiGetId(docId, firstrowId, FP_FirstCellInRow);
/* If there are two cells in the row, straddle them. */
if (F_ApiGetInt(docId, tableId, FP_TblNumCols) < 2)
F_ApiAlert("Not enough columns!", FF_ALERT_CONTINUE_NOTE);
else F_ApiStraddleCells(docId, cellId, 1, 2);
. . .

Executing FrameMaker commands
The following sections describe how to programmatically execute FrameMaker
commands.
Manipulating elements
The API provides several functions that allow you to execute basic commands that
manipulate elements.

272

FDK Programmer’s Guide

Executing FrameMaker commands

...

Executing Commands with API Functions

The syntax for these functions is:
VoidT
VoidT
VoidT
VoidT
VoidT
VoidT
VoidT

F_ApiDemoteElement(F_ObjHandleT docId);
F_ApiMergeIntoFirst(F_ObjHandleT docId);
F_ApiMergeIntoLast(F_ObjHandleT docId);
F_ApiPromoteElement(F_ObjHandleT docId);
F_ApiSplitElement(F_ObjHandleT docId);
F_ApiUnWrapElement(F_ObjHandleT docId);
F_ApiWrapElement(F_ObjHandleT docId,
F_ObjHandleT edefId);

This argument

Means

docId

ID of the document containing selected text and/or structure elements

edefId

ID of element definition for the new element

These functions behave like the corresponding commands in the user interface. They all
use the current text or element selection in the specified document to determine which
text and elements to manipulate. You can allow the user to set the text or element
selection, or you can do it programmatically. For information on setting the text
selection programmatically, see “Getting and setting the insertion point or text
selection” on page 321. For more information on setting the element selection
programmatically, see “Getting and setting the structural element selection” on
page 329
Importing element definitions into FrameMaker documents and books
To import element definitions from a FrameMaker document or book to a FrameMaker
document or book, use F_ApiSimpleImportElementDefs().

FDK Programmer’s Guide 273

7

Executing Commands with API Functions

Executing FrameMaker commands

The syntax for F_ApiSimpleImportElementDefs() is:
IntT F_ApiSimpleImportElementDefs(
F_ObjHandleT docOrBookId,
F_ObjHandleT fromDocOrBookId,
IntT importFlags);
This argument

Means

docOrBookId

The ID of the document or book to import element definitions to.

fromDocOrBookId

The ID of the document or book from which to import element
definitions.

importFlags

See the following table for the flags that you can OR into this
parameter.

The following table lists flags that you can OR into the importFlags parameter:
Flag

Meaning

FF_IED_REMOVE_OVERRIDES

Clear format overrides.

FF_IED_REMOVE_BOOK_INFO

If docOrBookId specifies a document, clear
formatting inherited from the parent book.

FF_IED_DO_NOT_IMPORT_EDD

If the document specified by fromDocOrBookId is
an EDD, don’t treat it as an EDD; just import its
element catalog.

FF_IED_NO_NOTIFY

Do not issue the FA_Note_PreImportElemDefs
or FA_Note_PostImportElemDefs
notifications.

If you import element definitions to a book, F_ApiSimpleImportElementDefs()
imports element definitions to each book component for which the
FP_ImportFmtInclude property is set to True.
Calling FrameMaker clients programmatically
Much of the structured document functionality FrameMaker provides is implemented in
FDK clients. To call this functionality programmatically, you must use
F_ApiCallClient().

274

FDK Programmer’s Guide

Executing FrameMaker commands

...

Executing Commands with API Functions

F_ApiCallClient() requires you to specify a client’s registered name and a string,
which it passes to the client. The following table lists FrameMaker functionality and the
registered names of the clients you can call to invoke it programmatically.
Functionality

Registered client name

Element catalog manager

Element Catalog Manager

Structure generator

Structure Generator

Reading and writing Structured documents
and reading, writing, and updating DTD
and EDD documents

FmDispatcher

The following table lists the strings you pass to the structure generator client to
programmatically generate structure in a document or book.
String

Meaning

INPUTDOCID objectID

The ID of the input document or book.

RULEDOCID objectID

The ID of the rule table document.

OUTPUTDOCNAME filename

The full pathname of the output document or book. This
string is optional. If you do not specify a pathname, the
structure generator leaves the document unsaved and open.

LOGNAME filename

The full pathname of a log file. This string is optional. If
you do not specify a pathname, the structure generator
leaves the log file unsaved and open.

StructureDoc

Instructs the structure generator to generate structure,
using the strings listed above.

FDK Programmer’s Guide 275

7

Executing Commands with API Functions

Executing FrameMaker commands

To programmatically generate structure for a document or a book, you call
F_ApiCallClient() multiple times, each time passing it one of the strings listed in
the table above. For example, the following code generates structure for a document:
. . .
F_ObjHandleT inputDocId, ruleTblDocId;
UCharT buf[64];
. . .
F_Sprintf(buf, "INPUTDOCID %d", inputDocId);
F_ApiCallClient("StructGen", buf);
F_Sprintf(buf, "RULEDOCID %d", ruleTblDocId);
F_ApiCallClient("StructGen", buf);
F_ApiCallClient("StructGen", "OUTPUTDOCNAME /tmp/mystruct.doc");
F_ApiCallClient("StructGen", "LOGNAME /tmp/logfile.doc");
F_ApiCallClient("StructGen", "StructureDoc");
. . .

Note that all of the documents you specify must be open before you call the structure
generator. If you are generating structure for a large number of documents, you can
greatly speed processing by opening the documents invisibly. To open a document
invisibly, set the FS_MakeVisible property of the Open script to False.
For a complete list of the strings you can pass to the structure generator and other
FrameMaker clients, see “F_ApiCallClient()” on page 85 in the FDK Programmer’s
Reference.

276

FDK Programmer’s Guide

8

Getting and Setting Properties

..................................
.....

5

This chapter describes how to make changes in a FrameMaker product session, book, or
document by getting and setting property values. It discusses how to get and set
individual properties and entire property lists. It also provides some tips for getting and
setting the properties of specific types of objects.

What you can do with object properties
In the FrameMaker product user interface, the user can change an object in a variety of
ways. For example, the user can change the size and fill pattern of a graphic object or
the starting page number of a book component.
Each API object has a property list, a set of properties describing its attributes. Your
API client can do anything a user can do to an object by getting and setting the
properties in the object’s property list. For example, your client can set properties to:


Change a graphic object’s size, fill pattern, or position in the back-to-front order



Make a document or book active



Change a book component’s position in a book



Change a paragraph’s format

Your client can also change properties that the user doesn’t have access to. For example,
your client can set properties to:


Make a document or book visible or invisible



Keep the FrameMaker product from reformatting a document every time a change is
made

The API ensures that your client doesn’t corrupt a document by setting properties to
illegal values. When you change a property, the API also automatically changes other
properties as needed to preserve the integrity of the document or book.
There are a number of read-only properties that you can get but not set. For a complete
list of object properties and their possible values, see Chapter 3, “Object Reference,” in
the FDK Programmer’s Reference.

FDK Programmer’s Guide 277

9

Getting and Setting Properties

Getting the IDs of the objects you want to change

To change a session, document, or book by setting object properties, follow these
general steps:
1 Find out which objects represent the things you want to change.
To change something in a session, book, or document, you need to know which objects
the API uses to represent it. For a description of how the API uses objects to represent
things in FrameMaker products, see Part II, “Frame Product Architecture.”
2 Get the IDs of the objects you want to change.
To set an object’s properties, you must specify its ID. The API provides functions for
retrieving object IDs.
3 Manipulate the objects’ properties.
The API provides functions for getting and setting individual properties and entire
property lists.
For example, the API represents a FrameMaker product session with an FO_Session
object. You don’t need to get a session’s ID, because there is only one session and its ID
is always FV_SessionId. To find all the session characteristics you can change, look
up “Session” on page 894 in Chapter 3, “Object Reference,” in the FDK Programmer’s
Reference.
You can, for example, change the session’s automatic save time. The API represents the
automatic save time with an integer (IntT) property named FP_AutoSaveSeconds.
To set it to 60 seconds, use the following code:
F_ApiSetInt(0,
FV_SessionId,
FP_AutoSaveSeconds,
60);

/*
/*
/*
/*

Sessions have no parent */
The session’s ID */
The property to set */
The value to set it to */

The following sections describe steps 2 and 3 in greater detail.

Getting the IDs of the objects you want to change
Every object in a session has an ID. To get or set the properties of a particular object,
you must specify its ID. In Frame book and document architecture, objects are
organized in linked lists: an object has properties that specify the IDs of other objects,
which have properties that specify the IDs of other objects, and so on. To get the IDs of
specific objects, you traverse the linked lists by querying these properties. For diagrams
and descriptions of the linked lists in Frame architecture, see Part II, “Frame Product
Architecture.”

278

FDK Programmer’s Guide

Getting the IDs of the objects you want to change

...

Getting and Setting Properties

To query a property that specifies an object ID, use F_ApiGetId(), which is defined
as:
F_ObjHandleT F_ApiGetId(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum);
This argument

Means

docId

The ID of the document, book, or session containing the object whose
property you want to query.

objId

The ID of the object whose property you want to query.

propNum

The property to query. Specify one of the API-defined constants, such as
FP_ActiveDoc.

F_ApiGetId() returns the ID specified by the property. If the property doesn’t
specify an ID or an error occurs, F_ApiGetId() returns 0.
To get an object’s ID, you start traversing at the object that represents the session (the
FO_Session object), because it is the only object whose ID (FV_SessionId) you
know from the start.
From the FO_Session object, you can get the IDs of the active and open documents
and books in the session. FO_Session objects have properties, named
FP_ActiveDoc and FP_ActiveBook, that specify the IDs of the active document or
book. A document or a book is active if it has input focus.
FO_Session objects also have properties, named FP_FirstOpenDoc and
FP_FirstOpenBook, that specify the first document and the first book in the linked
lists of open documents and books in a session. FO_Doc objects have a property named
FP_NextOpenDocInSession that specifies the ID of the next FO_Doc object in the
list of open documents. FO_Book objects have a property named
FP_NextOpenBookInSession that specifies the ID of the next FO_Book object in
the list of open books. If an FO_Doc or an FO_Book object is the last object in the
list, its FP_NextOpenDocInSession or FP_NextOpenBookInSession
property is set to 0. For a diagram of how the API represents the documents and books
in a session, see Figure 1-2 on page 69.

FDK Programmer’s Guide 279

9

Getting and Setting Properties

Getting the IDs of the objects you want to change

Suppose you want to display the IDs of the active document and all the open documents
in a session. You can use the following code to do this:
. . .
#include "futils.h"
F_ObjHandleT docId;
UCharT msg[256];
/* Get the ID of the active document and display it. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if (docId)
{
F_Sprintf(msg, "The active document’s ID is 0x%x.", docId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
}
/* Get ID of the first document in list of open documents. */
docId = F_ApiGetId(0, FV_SessionId, FP_FirstOpenDoc);
/* Traverse list of open documents and display their IDs. */
while (docId)
{
F_Sprintf(msg, "The document’s ID is 0x%x.", docId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
docId = F_ApiGetId(FV_SessionId, docId,
FP_NextOpenDocInSession);
}
. . .

This code displays the ID of the active document twice, because the active document is
included in the list of open documents.
The linked list of open documents in a session isn’t in any particular order. The first
document in the list is not necessarily the active document or the first document that was
opened.
Another way to get a document ID is to use F_ApiSimpleOpen(), F_ApiOpen(),
or F_ApiSimpleNewDoc() to open or create the document. These functions all
return the IDs of the document they open or create.

280

FDK Programmer’s Guide

Getting the IDs of the objects you want to change

...

Getting and Setting Properties

Traversing lists of objects in a document
Once you have the ID of a document, you can query its properties to get to the lists of
objects that it contains. The document has a number of properties that point to these
lists. For example, the document’s FP_FirstGraphicInDoc property specifies the
ID of the first graphic object in the list of its graphic objects and its
FP_FirstBodyPageInDoc property specifies the first body page in the list of its
body pages. Except for the lists of pages, the lists are completely unordered. For
example, the first graphic object in the list of graphic objects is not necessarily the first
graphic that appears in the document.
Suppose you want to traverse the list of all the paragraphs in the active document. To do
this, you can use the following code:
. . .
#include "futils.h"
F_ObjHandleT docId, pgfId;
UCharT msg[256];
/* Get the ID of the active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of the first paragraph in the list of paragraphs. */
pgfId = F_ApiGetId(FV_SessionId, docId, FP_FirstPgfInDoc);
/* Traverse the list of paragraphs and display their IDs.
** Even empty documents have several paragraphs, because text
** columns on master pages contain paragraphs.
*/
while (pgfId)
{
F_Sprintf(msg, "The paragraph’s ID is 0x%x.", pgfId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
pgfId = F_ApiGetId(docId, pgfId, FP_NextPgfInDoc);
}
. . .

The paragraphs in the list are not ordered.

FDK Programmer’s Guide 281

9

Getting and Setting Properties

Getting the IDs of the objects you want to change

Traversing lists of graphic objects
The API does not maintain separate lists of the different types of graphic objects in a
document. For example, a document’s text columns (FO_TextFrame objects),
rectangles (FO_Rectangle objects), and anchored frames (FO_AFrame objects) are
all in the same list. To determine objects’ types as you traverse them, use
F_ApiGetObjectType().
The syntax for F_ApiGetObjectType() is:
UIntT F_ApiGetObjectType(F_ObjHandleT docId,
F_ObjHandleT objId);
This argument

Means

docId

The ID of the document, book, or session containing the object

objId

The ID of the object whose type you want to get

For example, the following code counts the number of anchored frames in the active
document:
. . .
#include "futils.h"
IntT numFrames = 0;
F_ObjHandleT docId, objId;
UCharT msg[256];
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of first graphic in the list of graphics. */
objId = F_ApiGetId(FV_SessionId, docId, FP_FirstGraphicInDoc);
/* Traverse list of graphics, counting anchored frames. */
while (objId)
{
if (F_ApiGetObjectType(docId,objId) == FO_AFrame) numFrames++;
objId = F_ApiGetId(docId, objId, FP_NextGraphicInDoc);
}
F_Sprintf(msg, "The document has %d anchored frames.",
numFrames);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
. . .

282

FDK Programmer’s Guide

Getting the IDs of the objects you want to change

...

Getting and Setting Properties

Traversing ordered lists of objects
Traversing the list of all the objects of a certain type in a document is useful if you want
to get every object of that type and the order doesn’t matter to you. However, it isn’t
very useful if you want the objects in some kind of order, such as the order in which they
appear on a document’s pages. To get objects in order, you must traverse the ordered
lists that the API maintains. There are ordered lists of the graphic objects in a frame, the
text columns within a flow, and many other objects. These lists can be deeply nested, for
example, when a frame contains a frame that contains some graphic objects.
There are a variety of object properties you can query to get to ordered lists. For
example, to get to the list of graphic objects in a frame, you can query the frame’s
FP_FirstGraphicInFrame or FP_LastGraphicInFrame properties. If you
already have one of the graphic object’s IDs, you can query its
FP_PrevGraphicInFrame and FP_NextGraphicInFrame properties to get to
the objects behind it and in front of it in the list. The order of the list corresponds to the
back-to-front order of the graphics in the frame. For information on the linked lists that
a particular object is included in, see the section that discusses that object in Chapter 2,
“Frame Document Architecture.”
Although there are ordered lists of the paragraphs within each of a document’s flows,
there is no ordered list of flows. You can get the paragraphs only in the order in which
they occur within an individual flow.

FDK Programmer’s Guide 283

9

Getting and Setting Properties

Getting the IDs of the objects you want to change

To get the paragraphs within an individual flow in order, you navigate from the flow to
the first text frame in the flow, to the first paragraph in that text frame. For example, to
get the paragraphs in a document’s main flow in order, you can use the following code:
. . .
#include "futils.h"
F_ObjHandleT docId, pgfId, flowId, textFrameId;
UCharT msg[256];
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of main flow, then the first text column in the
* flow, then the first paragraph in that text column.
*/
flowId = F_ApiGetId(FV_SessionId, docId, FP_MainFlowInDoc);
textFrameId = F_ApiGetId(docId, flowId,
FP_FirstTextFrameInFlow);
pgfId = F_ApiGetId(docId, textFrameId, FP_FirstPgf);
/* Traverse ordered list of paragraphs in the flow. */
while (pgfId)
{
F_Sprintf(msg, "The paragraph’s ID is 0x%x.", pgfId);
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
pgfId = F_ApiGetId(docId, pgfId, FP_NextPgfInFlow);
}
. . .

For a diagram of the links between flows, text frames, and paragraphs, see “The list of
paragraphs in a flow” on page 104.

Getting the IDs of selected objects
Document objects have properties that allow you to get the IDs of the following types
of selected objects:


Graphic objects



Tables and table rows

To get the IDs of selected structural elements in FrameMaker documents, you must call
a special function, F_ApiGetElementRange().

284

FDK Programmer’s Guide

Getting the IDs of the objects you want to change

...

Getting and Setting Properties

For background information on selection in Frame documents, see “How the API
represents the selection in a document” on page 80. For information on getting selected
text, see “Getting and setting the insertion point or text selection” on page 321.
Getting the IDs of selected graphic objects
The API maintains an unordered list of all the selected graphic objects in a document.
To manipulate graphic objects the user has selected, you traverse this list. For example,
the following code sets the fill pattern of all the selected graphic objects in the active
document to black:
. . .
F_ObjHandleT docId, objId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
objId = F_ApiGetId(FV_SessionId, docId,
FP_FirstSelectedGraphicInDoc);
while (objId)
{
F_ApiSetInt(docId, objId, FP_Fill, FV_FILL_BLACK);
objId = F_ApiGetId(docId, objId,
FP_NextSelectedGraphicInDoc);
}
. . .

Getting the IDs of selected tables and table rows
If a table is selected, you can get its ID by querying the document property,
FP_SelectedTbl. A table is considered selected if any of its cells are selected or the
insertion point is in any of its cells.
To get the IDs of the rows selected within a table, query the FO_Tbl object’s
FP_TopRowSelection and FP_BottomRowSelection properties.
FP_TopRowSelection specifies the ID of the row at the top of the selection;
FP_BottomRowSelection specifies the ID of the row at the bottom of the selection.
To determine which cells in a row are selected, query a table’s FP_LeftColNum and
FP_RightColNum properties. FP_LeftColNum specifies the number (starting from
0) of the leftmost selected column; FP_RightColNum specifies the number of the
rightmost selected column.
If a range of text that includes several tables is selected, and you want to get the tables’
IDs, you must get the text selection and traverse all the table anchor text items in it. For
more information on getting the text selection, see “Getting and setting the insertion
point or text selection” on page 321.

FDK Programmer’s Guide 285

9

Getting and Setting Properties

Getting the IDs of the objects you want to change

Getting the IDs of selected structural elements
For information on getting the IDs of selected structural elements, see “Getting and
setting the structural element selection” on page 329.

Getting the IDs of formats and other named objects
The following are some of the types of objects that are named (identified by a unique
name).


FO_CharFmt



FO_Color



FO_CombinedFontDfn



FO_Command



FO_CondFmt



FO_ElementDef



FO_Flow



FO_FmtChangeList



FO_MarkerType



FO_MasterPage



FO_Menu



FO_PgfFmt



FO_TblFmt



FO_UnanchoredFrame (named frames on reference pages)



FO_VarFmt



FO_XRefFmt

The API maintains all the named objects of a particular type in a linked list. To get the
objects, you can query FO_Doc properties and traverse the list. For example, to get all
the variable formats in a document, query the FO_Doc object’s
FP_FirstVarFmtInDoc property, and then traverse the FP_NextVarFmtInDoc
properties from one FO_VarFmt object to the next.

286

FDK Programmer’s Guide

Getting the IDs of the objects you want to change

...

Getting and Setting Properties

If you only want the ID for a single named object, it is usually easier to use
F_ApiGetNamedObject(). The syntax for F_ApiGetNamedObject() is:
F_ObjHandleT F_ApiGetNamedObject(F_ObjHandleT docId,
IntT objType,
StringT name);
This argument

Means

docId

The ID of the document or book containing the object

objType

The type of object (for example, FO_VarFmt)

name

The name of the object for which to get the ID

For example, the following code gets the ID of the Paragraph Catalog format named
Body in the active document:
. . .
F_ObjHandleT docId, pgfFmtId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
pgfFmtId = F_ApiGetNamedObject(docId, FO_PgfFmt, "Body");
. . .

Getting IDs for objects that have persistent identifiers
FrameMaker products assign a persistent unique identifier (UID) to each object in a
document that isn’t identified by a name. The UID, unlike the object’s ID, does not
change from one session to another. No matter how many times you open and exit a
document, an object’s UID remains the same.
It is important to note that cut and paste functions will assign new UID’s to the text. For
example conditionalizing text will change a paragraph’s UID.
To get an object’s UID, you query its FP_Unique property with F_ApiGetInt().
If you already know an object’s UID, you can find
its ID in the current session by calling F_ApiGetUniqueObject().

FDK Programmer’s Guide 287

9

Getting and Setting Properties

Manipulating properties

The syntax for F_ApiGetUniqueObject() is:
F_ObjHandleT F_ApiGetUniqueObject(F_ObjHandleT docId,
IntT objType
IntT unique);
This argument

Means

docId

The ID of the document containing the object

objType

The object type (for example FO_Pgf)

unique

The object’s UID

For an example of how you can use UIDs, see “F_ApiGetUniqueObject()” on page 268
of the FDK Programmer’s Reference.

Manipulating properties
The API allows you to get and set either an individual property or a property list for an
object. It is generally easier to get and set properties individually. However, some tasks,
such as applying a Paragraph Catalog format to a paragraph, are easier to perform by
getting and setting property lists.

288

FDK Programmer’s Guide

Manipulating properties

...

Getting and Setting Properties

Getting and setting individual properties
To get or set an individual property, use the F_ApiGetPropertyType() or
F_ApiSetPropertyType() function that corresponds to the property’s data type.
For example, to get an integer, enum, or boolean (IntT data type) property, use
F_ApiGetInt(). To set a property that represents a set of strings (F_StringsT data
type), use F_ApiSetStrings(). The data types of API properties are listed in
Chapter 3, “Object Reference,” in the FDK Programmer’s Reference. The following
table lists the functions you use to set different types of properties.
The API also provides special functions to get and set properties that are identified by
names. These functions are used for getting and setting inset properties only. They are
discussed in Chapter 12, “Using Imported Files and Insets.”
Property’s data type

Functions to get and set property

F_AttributesT

F_ApiGetAttributes()
F_ApiSetAttributes()

F_AttributeDefsT

F_ApiGetAttributeDefs()
F_ApiSetAttributeDefs()

F_ElementCatalogEntriesT

F_ApiGetElementCatalog()

F_ElementFmtsT

F_ApiGetElementFormats()
F_ApiSetElementFormats()

F_ElementRangeT

F_ApiGetElementRange()
F_ApiSetElementRange()

F_ObjHandleT

F_ApiGetId()
F_ApiSetId()

IntT (including boolean, enum, and ordinal)

F_ApiGetInt()
F_ApiSetInt()

F_IntsT

F_ApiGetInts()
F_ApiSetInts()

MetricT

F_ApiGetMetric()
F_ApiSetMetric()

F_MetricsT

F_ApiGetMetrics()
F_ApiSetMetrics()

F_PointsT

F_ApiGetPoints()
F_ApiSetPoints()

StringT

F_ApiGetString()
F_ApiSetString()

FDK Programmer’s Guide 289

9

Getting and Setting Properties

Manipulating properties

Property’s data type

Functions to get and set property

F_StringsT

F_ApiGetStrings()
F_ApiSetStrings()

F_TabsT

F_ApiGetTabs()
F_ApiSetTabs()

F_TextLocT

F_ApiGetTextLoc()
F_ApiSetTextLoc()

F_TextRangeT

F_ApiGetTextRange()
F_ApiSetTextRange()

The syntax for most F_ApiGetPropertyType() and
F_ApiSetPropertyType() functions is similar. For example, the syntax
for F_ApiGetInt() is:
IntT F_ApiGetInt(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum);
This argument

Means

docId

The ID of the document, book, or session containing the object. If the object
is a session, specify 0.

objId

The ID of the object whose property you want to query.

propNum

The property to query (for example, FP_FnNum).

The syntax for F_ApiSetString() is:
VoidT F_ApiSetString(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum,
StringT setVal);

290

This argument

Means

docId

The ID of the document, book, or session containing the object

objId

The ID of the object whose property you want to set

propNum

The property to set, for example, FP_PrintFileName

setVal

The string to which to set the property

FDK Programmer’s Guide

Manipulating properties

...

Getting and Setting Properties

You can look up the exact syntax of an F_ApiGetPropertyType() or
F_ApiSetPropertyType() function in Chapter 2, “FDK Function Reference,” in
the FDK Programmer’s Reference.
Suppose you want your client to change some characteristics of the Heading1 paragraph
format. To find out how the API represents paragraph formats, look up paragraph
formats in Part II, “Frame Product Architecture.” For a complete list of paragraph
format properties, see Chapter 3, “Object Reference,” in the FDK Programmer’s
Reference.
The following code demonstrates how to change different types of paragraph format
properties:
. . .
#define in (MetricT) (72 * 65536) /* A Frame metric inch */
F_ObjHandleT docId, pgfFmtId;
/* Get the ID of Heading1 format in active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
pgfFmtId = F_ApiGetNamedObject(docId, FO_PgfFmt, "Heading1");
/* Set Next Pgf Tag to Heading2. */
F_ApiSetString(docId, pgfFmtId, FP_NextTag, "Heading2");
/* Turn on Keep With Next. */
F_ApiSetInt(docId, pgfFmtId, FP_KeepWithNext, True);
/* Set the left indent to 1 inch. */
F_ApiSetMetric(docId, pgfFmtId, FP_LeftIndent, in);
. . .

This code changes only the Heading1 Paragraph Catalog format. It does not change the
formats of paragraphs that have already been tagged with Heading1.

Getting and setting property lists
Because most objects have relatively long property lists, it is often easier to get and set
individual properties. However, to perform the following types of tasks, you may need
to get and set entire property lists:


Getting and setting text properties



Applying table, paragraph, and character formats



Copying graphic object properties

FDK Programmer’s Guide 291

9

Getting and Setting Properties

Manipulating properties

To get and set property lists, you need to understand how the API represents them. For
more information, see “Property lists” on page 64.
F_ApiGetProps() and F_ApiSetProps() make it easy to get and set property
lists.
The syntax for these functions is:
F_PropValsT F_ApiGetProps(F_ObjHandleT docId,
F_ObjHandleT objId);
VoidT F_ApiSetProps(F_ObjHandleT docId,
F_ObjHandleT objId,
F_PropValsT *setVal);
This argument

Means

docId

The ID of the session, book, or document containing the object

objId

The ID of the object to get or set the property list for

setVal

The property list to apply to the object

The F_PropValsT structure returned by F_ApiGetProps() references memory
that is allocated by the API. Use F_ApiDeallocatePropVals() to free this
memory when you are done with it. If F_ApiGetProps() fails, the API sets the len
field of the returned structure to 0.

292

FDK Programmer’s Guide

Manipulating properties

...

Getting and Setting Properties

Example
The following code copies the properties from one selected graphic object to another:
. . .
F_PropValsT props;
F_ObjHandleT obj1Id, obj2Id, docId;
/* Get ID of active document and the two selected objects. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
obj1Id = F_ApiGetId(FV_SessionId, docId,
FP_FirstSelectedGraphicInDoc);
obj2Id = F_ApiGetId(docId, obj1Id, FP_NextSelectedGraphicInDoc);
/* Make sure two objects are selected, then copy properties. */
if (!(obj1Id && obj2Id)) F_ApiAlert("First select two objects.",
FF_ALERT_CONTINUE_WARN);
else
{
props = F_ApiGetProps(docId, obj1Id);
if(props.len == 0) return; /* Get props failed. */
F_ApiSetProps(docId, obj2Id, &props);
}
. . .

Because a graphic object’s x and y coordinates are included in its property list, this code
moves the two graphic objects to the same location, with one object overlaying the
other.
After you have copied a property list to an object, you can customize the list by
changing individual properties.
Manipulating property lists directly
If you are setting individual text properties or using scriptable functions, such as
F_ApiOpen(), you need to manipulate property lists directly.
The order of the properties in property lists is not guaranteed to remain the same in
future versions of FrameMaker products and the Frame API. So, to get a particular
property in a list, you must traverse the entire property list and check each property’s
identifier until you find it. The API provides a convenience routine named
F_ApiGetPropIndex() that does this for you.

FDK Programmer’s Guide 293

9

Getting and Setting Properties

Manipulating properties

The syntax for F_ApiGetPropIndex() is:
IntT F_ApiGetPropIndex(F_PropValsT *pvp,
IntT propNum);
This argument

Means

pvp

The property list

propNum

The property whose index you want to get

F_ApiGetPropIndex() returns the index of the F_PropValT structure that
represents the property’s property-value pair. If you specify an invalid property for
propNum, F_ApiGetPropIndex() returns FE_BadPropNum.
Suppose you want to display the session property that provides the name of the current
FrameMaker product. The easy way to do this would be to use the following code:
. . .
StringT productName;
productName = F_ApiGetString(0, FV_SessionId, FP_ProductName);
F_ApiAlert(productName, FF_ALERT_CONTINUE_NOTE);
. . .

To do the same thing by getting the property list for the session and accessing the
property directly, use the following code:
. . .
IntT i;
F_PropValsT props;
props = F_ApiGetProps(0, FV_SessionId);
i = F_ApiGetPropIndex(&props, FP_ProductName);
F_ApiAlert(props.val[i].propVal.u.sval,
FF_ALERT_CONTINUE_NOTE);
. . .

Allocating and deallocating memory for properties
The F_ApiGetPropertyType() functions that return pointers to arrays make
copies of the arrays, allocating memory for them. For example, F_ApiGetString()
does not return a pointer to the actual string used by the FrameMaker product. Instead,
it creates a copy of the string and returns a pointer to the copy. The API does not

294

FDK Programmer’s Guide

Getting and setting session properties

...

Getting and Setting Properties

deallocate memory used by the copy of the string. When you are done with it, you must
deallocate it.
Similarly, when you call a F_ApiSetPropertyType() function such as
F_ApiSetString(), the function does not set a pointer to the string you pass to it.
Instead it copies the string. The API does not deallocate the string you pass. When you
are done with it, you must deallocate it.
For example, the following code queries and displays the FP_OpenDir property. It
uses the FDE function, F_Free(), to free the returned string.
. . .
#include "fstrings.h"
#include "fmemory.h"
StringT openDir;
openDir = F_ApiGetString(0, FV_SessionId, FP_OpenDir);
F_ApiAlert(openDir, FF_ALERT_CONTINUE_NOTE);
F_Free(openDir);
. . .

For more information on FDE functions, see Part III, “Frame Development
Environment (FDE).”
Some API functions return structures containing pointers to arrays. The API allocates
memory for these arrays. When you are done with this memory, you must deallocate it.
The API provides convenience functions, such as F_ApiDeallocatePropVals(),
F_ApiDeallocateStrings(), and F_ApiDeallocateMetrics(), which
you can use for this.
For example, to get the property list for an object and then deallocate it, use code similar
to the following:
. . .
F_PropValsT props;
F_ObjHandleT objId, docId;
props = F_ApiGetProps(docId, objId);
. . .
F_ApiDeallocatePropVals(&props);
. . .

Getting and setting session properties
The following sections describe useful tasks you can perform by getting and setting
session properties.
FDK Programmer’s Guide 295

9

Getting and Setting Properties

Getting and setting session properties

Making a document or book active
In addition to finding out which document is active by getting the session’s
FP_ActiveDoc property, you can make a document active by setting this property.
For example, the following code makes the document specified by docId active:
. . .
F_ObjHandleT docId;
F_ApiSetId(0, FV_SessionId, FP_ActiveDoc, docId);
. . .

When you make a visible document active, its window gets input focus. On some
platforms, the windowing system highlights a window’s title bar or brings it to the front.
. . .

Disabling redisplaying to avoid screen flicker
If you change numerous properties at once, it may cause screen flicker, an effect that
occurs when a FrameMaker product executes a long series of changes that aren’t userinitiated. By default, FrameMaker products reformat after each change.
You can avoid screen flicker by batching changes. To batch changes,
set the FO_Session property FP_Displaying to False. As long as
FP_Displaying is set to False, the FrameMaker product does not refresh the
documents in the current session when you or the user changes them.
To refresh the documents, you must call F_ApiRedisplay() for each changed
document.
The syntax for F_ApiRedisplay() is:
IntT F_ApiRedisplay(F_ObjHandleT docId);

296

FDK Programmer’s Guide

Getting and setting session properties

...

Getting and Setting Properties

For example, to change a number of properties at once, use code similar to the
following:
. . .
F_ObjHandleT docId;
F_ApiSetInt(0, FV_SessionId, FP_Displaying, False);
/* Change multiple properties here. */
F_ApiSetInt(0, FV_SessionId, FP_Displaying, True);
F_ApiRedisplay(docId); /* Must be called for each document */
. . .

While FP_Displaying is set to False, the FrameMaker product doesn’t update the
display at all. In some cases, you may want the FrameMaker product to update the
display but to delay reformatting documents while you change them. To do this, set the
FO_Session property FP_Reformatting to False. After you have reset
FP_Reformatting to True, refresh the documents that you have changed by calling
F_ApiReformat() for each document.

FDK Programmer’s Guide 297

9

Getting and Setting Properties

Getting and setting document properties

Getting and setting document properties
The following sections describe useful tasks you can perform by getting and setting
document properties.

Getting a document’s pathname
A document’s absolute pathname is specified by its FP_Name property. The following
code displays the active document’s absolute pathname:
. . .
F_ObjHandleT docId;
StringT docName;
/* Get the document ID and name. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
docName = F_ApiGetString(FV_SessionId, docId, FP_Name);
F_ApiAlert(docName, FF_ALERT_CONTINUE_NOTE);
F_Free(docName);
. . .

Manipulating document windows
The API provides several properties that allow you to manipulate document and book
windows. To change a document window’s size and screen location, set the document’s
FP_ScreenX, FP_ScreenY, FP_ScreenWidth, and FP_ScreenHeight
properties. To bring the window to the front, set the document’s FP_IsInFront
property.

Setting a document or book title bar
The API allows you to set the title bars of both documents and books. By default, a
document or book’s title bar displays its name. However, you can make it display
another string by setting the document or book’s FP_Label property to the string. For
example, the following code displays the string MyTitle in the title bar of the active
document:
. . .
F_ObjHandleT docId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
F_ApiSetString(FV_SessionId, docId, FP_Label, "MyTitle");
. . .

298

FDK Programmer’s Guide

Getting and setting document properties

...

Getting and Setting Properties

After you set a document’s title bar, it doesn’t change until you reset it or the user closes
the document.
Setting the title bar of a document or book doesn’t change the name of the document or
book file itself. If you set the document or book title bar and the user closes and reopens
the document or book, the document or book name appears in the title bar again.

Setting a document or book status bar
The API allows you to set the status bars of both documents and books. If your client
conducts extensive processing, it can display status messages in the status bar to inform
users of its progress. To set the status bar of a document or a book, set its
FP_StatusLine property.
The string you set FP_StatusLine to remains in the status bar only until a client or
the FrameMaker product overwrites it. FrameMaker products overwrite the status bar
frequently. For example, every time the user moves the insertion point to a different
paragraph in a document, the FrameMaker product redisplays the paragraph format in
the status bar.

Enhancing performance by making documents invisible
The API allows you to make a document invisible. Your client can still make changes
to an invisible document. If your client needs to batch process multiple documents,
using invisible documents can increase its performance considerably.
To make a document invisible, you can use the following code:
. . .
F_ObjHandleT docId;
F_ApiSetInt(FV_SessionId, docId, FP_IsOnScreen, False);
. . .

You can also open documents invisibly by setting the FP_MakeVisible property of
the Open script to False.
..............................................................................

IMPORTANT: Because an invisible document can’t get input focus, it can’t be the active
document specified by the session property FP_ActiveDoc. You can’t send f-codes to
an invisible document.
..............................................................................

FDK Programmer’s Guide 299

9

Getting and Setting Properties

Getting and setting document properties

Displaying a particular page
Document objects (FO_Doc) have a property named FP_CurrentPage that specifies
the ID of the current page. The current page is the page that appears on the screen. If
more than one page appears on the screen, it is the page that appears with a dark border
around it. You can make a page current by making the document that contains it the
active document and then setting the document’s FP_CurrentPage property to the
page’s ID.
For example, the following code displays the second body page and then the first
reference page of the active document:
. . .
F_ObjHandleT docId, bPg1Id, bPg2Id, rPg1Id;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get second body page ID. */
bPg1Id = F_ApiGetId(FV_SessionId, docId, FP_FirstBodyPageInDoc);
bPg2Id = F_ApiGetId(docId, bPg1Id, FP_PageNext);
if (bPg2Id)
{
F_ApiSetId(FV_SessionId, docId, FP_CurrentPage, bPg2Id);
F_ApiAlert("Now at 2nd body page.", FF_ALERT_CONTINUE_NOTE);
}
/* Go to first reference page. */
rPg1Id = F_ApiGetId(FV_SessionId, docId, FP_FirstRefPageInDoc);
if (rPg1Id)
F_ApiSetId(FV_SessionId, docId, FP_CurrentPage, rPg1Id);
. . .

300

FDK Programmer’s Guide

Getting and setting graphic object properties

...

Getting and Setting Properties

Getting and setting graphic object properties
The following sections describe useful tasks you can perform by getting and setting
graphic object properties.

Changing an object’s size and location within a frame
Each graphic object has FP_Height and FP_Width properties, which specify its
height (the distance between its highest and lowest points) and its width (the distance
between its leftmost and rightmost points). To change an object’s size, use
F_ApiSetMetric() to set these properties. For example, the following code
increases a selected object’s width by 10 points:
. . .
#define pts (MetricT) 65536 /* Frame metric point */
F_ObjHandleT docId, objId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of selected object. */
objId = F_ApiGetId(FV_SessionId, docId,
FP_FirstSelectedGraphicInDoc);
/* Get object’s current width and add 10 points to it. */
if (objId)
F_ApiSetMetric(docId, objId, FP_Width,
F_ApiGetMetric(docId, objId, FP_Width) + 10*pts);
. . .

If you set the FP_Height and FP_Width properties of a polyline or
polygon, the API changes all the object’s vertices proportionally. If you
want to change a polygon or polyline’s vertices independently, use
F_ApiSetPoints() to set its FP_Points property. For an example of how to set
the FP_Points property, see “F_ApiSetPoints()” on page 422 of the FDK
Programmer’s Reference.
All graphic objects have an FP_LocX property, which specifies the distance of the
object’s leftmost point from the left side of the parent frame, and an FP_LocY property,
which specifies the distance of the object’s uppermost point from the top of its parent
frame. To change an object’s location within a frame, use F_ApiSetMetric() to set
these properties.

FDK Programmer’s Guide 301

9

Getting and Setting Properties

Getting and setting graphic object properties

Moving graphics forward or back in the draw order
FrameMaker products maintain the graphic objects in each frame in a linked list. Each
graphic object has FP_PrevGraphicInFrame and FP_NextGraphicInFrame
properties that specify the graphic objects before and after it in the list. The order of this
list corresponds to the back-to-front draw order. The first object in the list is the first
object the FrameMaker product draws, and therefore appears in back of objects later in
the list. To move a graphic object forward or back in the draw order, you change its
FP_PrevGraphicInFrame or FP_NextGraphicInFrame property so that it
specifies a different object. You need to change only one of these properties. The
FrameMaker product automatically changes the other one for you.
It also automatically changes the FP_PrevGraphicInFrame or
FP_NextGraphicInFrame properties of the object’s siblings.
To move an object all the way to the back of the objects in a frame, set its
FP_PrevGraphicInFrame property to 0. To move an object all the way to the front,
set its FP_NextGraphicInFrame property to 0.
For example, the following code moves a selected graphic object forward one level:
. . .
F_ObjHandleT docId, objId, sibId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of one (and only one) selected object. */
objId = F_ApiGetId(FV_SessionId, docId,
FP_FirstSelectedGraphicInDoc);
if (!objId || F_ApiGetId(docId, objId,
FP_NextSelectedGraphicInDoc))
F_ApiAlert("Select a single object", FF_ALERT_CONTINUE_NOTE);
else
{
/* Try to get ID of object in front of selected object. */
sibId = F_ApiGetId(docId, objId, FP_NextGraphicInFrame);
/* If there is an object in front, put it behind. */
if(sibId)
F_ApiSetId(docId, objId, FP_PrevGraphicInFrame, sibId);
}
. . .

302

FDK Programmer’s Guide

Getting and setting graphic object properties

...

Getting and Setting Properties

Moving graphic objects to different frames or pages
To move a graphic object to a different frame, set its FP_FrameParent property to
the ID of that frame. The API automatically changes all the properties that need to be
changed to maintain the lists of objects in the object’s old and new parent frames.
To move a graphic object to a different page, set its FP_FrameParent property to the
ID of a frame on that page. All pages have an invisible frame, called a page frame. To
put a graphic object directly on a page, set its FP_FrameParent property to the ID of
the page’s page frame. For more information on page frames, see “How the API
represents pages” on page 86.
For an example of how to move objects from a frame to a page frame, see
“F_ApiSetId()” on page 408 of the FDK Programmer’s Reference.

Grouping objects
To group a set of objects, you first use F_ApiNewGraphicObject() to create a
group (FO_Group) object. Then you add the objects to the group object by setting their
FP_GroupParent properties to the ID of the group object. The objects must be in the
same frame as the group object. For information on how to use
F_ApiNewGraphicObject(), see “Creating graphic objects” on page 361.
To remove an object from a group, set the object’s FP_GroupParent property to 0.

Copying properties from one graphic object to another
Each type of graphic object has a number of properties, such as FP_Fill and
FP_BorderWidth, which are common to all graphic objects. Some of these properties
don’t manifest themselves for all graphic objects. For example, rectangles have an
FP_ArrowType property, although they don’t have arrowheads. For a list of properties
common to all graphic objects, see “Common graphics properties” on page 840 of the
FDK Programmer’s Reference.
You can use F_ApiGetProps() and F_ApiSetProps() to copy common
properties from one graphic object to another, as shown in the example in “Getting and
setting property lists” on page 291. When you copy properties from one graphic object
to another, the objects do not have to be the same type. For example, you can copy the
properties from a line to a rectangle. The API copies only the common properties,
leaving properties that are specific to the rectangle, such as
FP_RectangleIsSmoothed, intact.

FDK Programmer’s Guide 303

9

Getting and Setting Properties

Getting and setting paragraph properties

Getting and setting paragraph properties
The following sections describe useful tasks you can perform by getting and setting
paragraph properties.

Applying paragraph and Paragraph Catalog formats
Paragraph (FO_Pgf) objects and Paragraph Catalog format (FO_PgfFmt) objects have
the same formatting properties. To apply the properties
from a paragraph to a Paragraph Catalog format or from a Paragraph Catalog format to
a paragraph, you can use F_ApiGetProps() and F_ApiSetProps().
For example, the following code applies the Paragraph Catalog format named Body to
the paragraph containing the insertion point:
. . .
F_PropValsT props;
F_TextRangeT tr;
F_ObjHandleT docId, pgfId, bodyFmtId;
StringT pgfName;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get ID of the Body Paragraph Catalog format. */
bodyFmtId = F_ApiGetNamedObject(docId, FO_PgfFmt, "Body");
if (!bodyFmtId) return;
/* Get text selection. For more information, see page 321. */
tr = F_ApiGetTextRange(FV_SessionId,docId, FP_TextSelection);
if(tr.beg.objId == 0) return;
/* Get properties from the Body Paragraph Catalog format. */
props = F_ApiGetProps(docId, bodyFmtId);
if(props.len == 0) return;
/* Apply Body properties to paragraph containing insertion
* point (or the beginning of the text selection).
*/
F_ApiSetProps(docId, tr.beg.objId, &props);
. . .

304

FDK Programmer’s Guide

Getting and setting paragraph properties

...

Getting and Setting Properties

If you have changed the Body format, you may want to reapply it to all paragraphs that
are tagged Body. To change these paragraphs, you must traverse every paragraph in the
document, determine if it’s tagged Body, and set its properties if it is. You can do this
by adding the following code to the code shown above:1
. . .
pgfId = F_ApiGetId(FV_SessionId, docId, FP_FirstPgfInDoc);
while (pgfId)
{
/* Get each paragraph’s tag and see if it’s Body. */
pgfName = F_ApiGetString(docId, pgfId, FP_Name);
if (F_StrEqual((StringT)"Body", pgfName))
F_ApiSetProps(docId, pgfId, &props);
F_Free(pgfName);
pgfId = F_ApiGetId(docId, pgfId, FP_NextPgfInDoc);
}
. . .

Adding tabs
To get and set the tabs for a paragraph or Paragraph Catalog format, use
F_ApiGetTabs() and F_ApiSetTabs().
The syntax for F_ApiGetTabs() and F_ApiSetTabs() is:
F_TabsT F_ApiGetTabs(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum);
VoidT F_ApiSetTabs(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum,
F_TabsT *setVal);

.................................
1. Some examples in this chapter use FDE functions, such as F_StrEqual(), F_Alloc(), and
F_Realloc(). For more information on using the FDE and these functions, see Part III, “Frame
Development Environment (FDE).”

FDK Programmer’s Guide 305

9

Getting and Setting Properties

Getting and setting paragraph properties

This argument

Means

docId

The ID of the document containing the paragraph or paragraph format whose
tabs you want to query or set.

objId

The ID of the paragraph or paragraph format whose tabs you want to query
or set.

propNum

The property to query. Specify FP_Tabs.

setVal

The F_TabsT structure to which to set the property.

The F_TabsT structure is defined as:
typedef struct {
UIntT len; /* The number of tabs in val */
F_TabT *val; /* Structures that describe the tabs */
} F_TabsT;

The F_TabT structure is defined as:
typedef struct {
MetricT x; /* Offset from paragraph’s left margin */
UCharT type; /* Constant for tab type, e.g. FV_TAB_RIGHT */
StringT leader; /* Characters before tab, e.g. "." */
UCharT decimal; /* Character for decimal tab, e.g. "." */
} F_TabT;

When you get the tabs for a paragraph or paragraph format, the API returns them in
left-to-right order in the val array. However, when you insert a tab, you don’t have to
insert it in this order. You just add it to the end of the val array. When you call

306

FDK Programmer’s Guide

Getting and setting paragraph properties

...

Getting and Setting Properties

F_ApiSetTabs(), the API sorts the tabs for you. For example, the following code
adds a 4-inch decimal tab to the Body paragraph format:
. . .
#include "fmemory.h"
#define in (MetricT) (65536 * 72)
F_ObjHandleT docId, pgfFmtId;
F_TabsT tabs;
/* Get the ID for the Body paragraph format. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
pgfFmtId = F_ApiGetNamedObject(docId, FO_PgfFmt, "Body");
if (!pgfFmtId) return;
/* Get the tabs and allocate space for new tab. */
tabs = F_ApiGetTabs(docId, pgfFmtId, FP_Tabs);
if (tabs.len++)
tabs.val=(F_TabT*)F_Realloc(tabs.val,
tabs.len*sizeof(F_TabT), NO_DSE);
else
tabs.val = (F_TabT*) F_Alloc(sizeof(F_TabT),NO_DSE);
/* Add the tab. */
tabs.val[tabs.len-1].type = FV_TAB_DECIMAL;
tabs.val[tabs.len-1].x = 4*in;
tabs.val[tabs.len-1].decimal = ’,’;
tabs.val[tabs.len-1].leader = F_StrCopyString(" ");
/* Set paragraph format’s tabs property to the array of tabs. */
F_ApiSetTabs(docId, pgfFmtId, FP_Tabs, &tabs);
F_ApiDeallocateTabs(&tabs);
. . .

FDK Programmer’s Guide 307

9

Getting and Setting Properties

Getting and setting book properties

Getting and setting book properties
To rearrange book components, you change their FP_PrevComponentInBook and
FP_NextComponentInBook properties.
For example, to move the first component in a book down one position,
you can use the following code:
. . .
F_ObjHandleT bookId, firstC, nextC;
bookId = F_ApiGetId(0, FV_SessionId, FP_ActiveBook);
firstC = F_ApiGetId(FV_SessionId, bookId,
FP_FirstComponentInBook);
nextC = F_ApiGetId(bookId, firstC, FP_NextComponentInBook);
if (nextC)
F_ApiSetId(bookId, firstC, FP_PrevComponentInBook, nextC);
else
F_ApiAlert("Only one component.", FF_ALERT_CONTINUE_NOTE);
. . .

308

FDK Programmer’s Guide

Getting and setting FrameMaker properties

...

Getting and Setting Properties

Getting and setting FrameMaker properties
There are some special issues involved in getting and setting properties in structured
FrameMaker documents. The following sections discuss some of these issues.

Traversing elements
To traverse the elements in a structured document, you use slightly different code than
you would use to traverse other objects, such as paragraphs. If you want to traverse all
the elements in a document, you can’t query only FP_NextSiblingElement
properties. You must also recursively traverse each element’s child elements. For
example, the following function prints the IDs of all the elements in a specified element:
. . .
VoidT traverseElement(F_ObjHandleT docId,
F_ObjHandleT elementId)
{
StringT name;
if (elementId)
{
elementId = F_ApiGetId(docId, elementId,
FP_FirstChildElement);
while(elementId)
{
F_Printf(NULL, (StringT) "Element ID is 0x%x.\n",
elementId);
traverseElement(docId, elementId);
elementId = F_ApiGetId(docId, elementId,
FP_NextSiblingElement);
}
}
}
. . .

Manipulating format change list properties
Most object types in the FDK have a single list of properties that applies to all objects
of that type. For example, if you call F_ApiGetProps() for any FO_Pgf object in
a document, it will always return the same list of properties. The values of the properties
may be different for each paragraph, but the list of properties will always be the same.
This is not the case with FO_FmtChangeList objects.
All FO_FmtChangeList objects have the following common properties:
FDK Programmer’s Guide 309

9

Getting and Setting Properties

Getting and setting FrameMaker properties



FP_Name



FP_NextFmtChangeListInDoc



FP_PgfCatalogReference

However, individual FO_FmtChangeList objects can have different sets of
additional properties, depending on what formatting characteristics they set. An
FO_FmtChangeList object can have all the properties listed under “Format change
lists” on page 826 of the FDK Programmer’s Reference, or it may have just a small
subset of these properties.
For example, the format change list in Figure 5-1 has only the common properties listed
above and the FP_FontFamily property. If you call F_ApiGetProps() for this
format change list, the function returns only four properties: the three common
properties listed above and the FP_FontFamily property.
Format change list: Code
Default font properties
Family: Courier
Figure 5-1 Format change list

If you attempt to use an F_ApiGetPropertyType() function to get a property that
a format change list doesn’t have, the function fails, setting FA_errno to
FE_PropNotSet.

310

FDK Programmer’s Guide

Getting and setting FrameMaker properties

...

Getting and Setting Properties

Adding properties to a format change list
To add a property to a format change list, you just set the property on
the FO_FmtChangeList object. You can do this by calling an
F_ApiSetPropertyType() function or by creating a property list containing the
property and calling F_ApiSetProps() to set the list on the object. For example, the
following code uses these two methods to add properties to the Code format change list:
. . .
#define pts (MetricT) 65536
F_PropValsT props;
F_ObjHandleT docId, changeListId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Create the Code change list. */
changeListId = F_ApiNewNamedObject(docId, FO_FmtChangeList,
"Code");
/* Add the FP_PairKern property to turn pair kerning off. */
F_ApiSetInt(docId, changeListId, FP_PairKern, False);
/* Set up list with FP_FontSize property to set size to 10. */
props = F_ApiAllocatePropVals(1);
props.val[0].propIdent.num = FP_FontSize;
props.val[0].propVal.valType = FT_Metric;
props.val[0].propVal.u.ival = 10*pts;
F_ApiSetProps(docId, changeListId, &props);
. . .

Note that the F_ApiSetProps() call in the code above only adds the
FP_FontSize property. It does not affect the other properties of the format change
list.

FDK Programmer’s Guide

311

9

Getting and Setting Properties

Getting and setting FrameMaker properties

Removing properties from a format change list
To remove a property from a format change list, call F_ApiDeletePropByName().
For example, the following code removes the FP_PairKern property from the Code
format change list:
. . .
F_ObjHandleT docId, changeListId;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
changeListId = F_ApiGetNamedObject(docId, FO_FmtChangeList,
"Code");
if (!changeListId) return;
F_ApiDeletePropByName(docId, changeListId, "FP_PairKern");
. . .

Setting format rule clause properties
Format rule clauses (FO_FmtRuleClause objects) have several properties that are
only indirectly settable. For example, you can’t set the FP_RuleClauseType
property directly. You can only set it indirectly by setting one of the following
properties:


FP_FormatName



FP_FmtChangeListTag



FP_FmtChangeList



FP_SubFmtRule

For example, if you set FP_FmtChangeListTag to Code, FrameMaker
automatically sets FP_RuleClauseType to FV_RC_CHANGELIST_TAG.
You can also set FP_FmtChangeList and FP_SubFmtRule only indirectly—by
calling F_ApiSubObject() to add a change list or subformat rule to the format rule
clause or by calling F_ApiDelete() to delete a change list or subformat rule. For an
example of how to use F_ApiSubObject(), see “Creating format rules, format rule
clauses, and format change lists” on page 369.

Setting element definition properties
Element definitions have the following properties that are only indirectly settable:

312



FP_TextFmtRules



FP_ObjectFmtRules



FP_PrefixRules

FDK Programmer’s Guide

Getting and setting FrameMaker properties



FP_SuffixRules



FP_FirstPgfRules



FP_LastPgfRules

...

Getting and Setting Properties

Each of these properties specifies a list of format rules. You can’t directly add a format
rule to one of these lists. Instead, you must call F_ApiSubObject().
F_ApiSubObject() creates an FO_FmtRule object and adds it to the end of the
specified list.
You also can’t directly remove a format rule from a list. Instead, you must call
F_ApiDelete() to delete the format rule. For example, the following code adds and
deletes a text format rule:
. . .
F_ObjHandleT docId, paraEdefId, fmtRuleId;
paraEdefId = F_ApiGetNamedObject(docId, FO_ElementDef, "Para");
/* Add a text format rule to the element definition. */
fmtRuleId = F_ApiSubObject(docId, paraEdefId,
FP_TextFmtRules);
/* Delete the text format rule. */
F_ApiDelete(docId, fmtRuleId);
. . .

Determining the formatting that applies to an element
To determine the formatting that applies to an element, you first get the following
properties:


FP_MatchingTextClauses



FP_MatchingObjectClauses



FP_MatchingPrefixClauses



FP_MatchingSuffixClauses



FP_MatchingFirstPgfClauses



FP_MatchingLastPgfClauses

Each of these properties specifies a list of format rule clauses that applies to the element.
Getting these properties only for the element itself is not sufficient to determine the
element’s formatting. These properties specify only the format rule clauses that are in
the element definition’s format rules (that is, the format rules specified by the element
definition’s FP_TextFmtRules, FP_ObjectFmtRules, FP_PrefixRules,
FDK Programmer’s Guide 313

9

Getting and Setting Properties

Getting and setting FrameMaker properties

FP_SuffixRules, FP_FirstPgfRules, and FP_LastPgfRules properties). In
order to fully determine the element’s formatting, you must find any applicable format
rule clauses that the element inherits from its ancestor elements. To determine whether
an element inherits format rule clauses from ancestor elements, you must traverse up the
structure tree and check the FP_MatchingClauses properties for each ancestor
element.

Determining which element contains an object
Frequently, it is useful to determine which element contains an object, such as a crossreference, a marker, or a table. The following table lists the properties you query to get
the ID of an object’s containing element.
Object

Property that returns ID of containing element

FO_Marker

FP_Element

FO_Fn
FO_XRef
FO_Var
FO_AFrame
FO_Row
FO_Cell
FO_Tbla

FP_TblElement
FP_TblTitleElement
FP_TblHeaderElement
FP_TblBodyElement
FP_TblFooterElement

a. If a table has a title or different types of rows, it can comprise several elements.

To determine the ID of the object an element contains, you query the element’s
FP_Object property.

314

FDK Programmer’s Guide

Getting and setting FrameMaker properties

...

Getting and Setting Properties

Specifying client data for an element
The FO_Element property FP_UserString allows your client to store its own data
with individual structural elements. The FP_UserString property is persistent
between sessions; after a client sets it, it remains the same until a client resets it. If an
element is cut and pasted, it retains its FP_UserString property. If an element is
copied and pasted, both the original element and the pasted element retain the
FP_UserString property.

Improving performance in FrameMaker clients
If you are using the API to create structured documents, you may need to add a large
number of elements or element definitions at a time. By default, FrameMaker validates
elements and applies format rules each time you add an element or element definition.
This can decrease performance considerably. To keep FrameMaker from validating
elements and applying format rules, set the FO_Session properties
FP_Validating and FP_ApplyFmtRules to False.

FDK Programmer’s Guide 315

9

316

Getting and Setting Properties

Getting and setting FrameMaker properties

FDK Programmer’s Guide

9

Manipulating Text

..................................
.....

6

This chapter describes how to use the API to manipulate text in Frame documents.
Specifically, it discusses how to:


Retrieve text from a document



Get and set the location of the insertion point or current text selection



Add and delete text



Get and set text formatting



Programmatically execute Clipboard operations

To better understand the material in this chapter, you may want to learn more about how
the API represents text. For information on this subject, see “Text” on page 112.

Getting text
Text in Frame documents is contained in objects, such as FO_Cell, FO_Element,
FO_Fn, FO_Pgf, FO_TextLine, FO_Var, FO_SubCol, FO_TextFrame, and
FO_Flow objects. To get text, you must get the ID of the object that contains it. For
information on getting object IDs, see “Getting the IDs of the objects you want to
change” on page 278.
Once you have the ID of an object that contains text, you use F_ApiGetText() to
retrieve the text.
The syntax for F_ApiGetText() is:
F_TextItemsT F_ApiGetText(F_ObjHandleT docId,
F_ObjHandleT objId,
IntT flags);
This argument

Means

docId

The ID of the document containing the object for which you want to get text.

FDK Programmer’s Guide 317

10

M a n i p u l a t i n g Te x t

Getting text

This argument

Means

objId

The ID of the object (FO_Flow, FO_Element, FO_Fn, FO_Pgf,
FO_Cell, FO_SubCol, FO_TextFrame, FO_TextLine, or FO_Var)
containing the text.

flags

Bit flags that specify the type of text items to retrieve. To get specific types
of text items, OR the constants that represent them (for example,
FTI_FlowBegin and FTI_String) into flags. To get all types of text
items, specify -1. For a complete list of the constants that represent text item
types, see “F_ApiGetText()” on page 242 in the FDK Programmer’s
Reference.

The F_TextItemsT structure contains an array of text items. Each string of characters
with common character and condition properties, each anchor, and each line or column
break in the text constitutes a separate text item.
F_TextItemsT is defined as:
typedef struct {
UIntT len; /* The number of text items */
F_TextItemT *val; /* Array of text items */
} F_TextItemsT;

The API represents each text item with an F_TextItemT structure. F_TextItemT
is defined as:
typedef struct {
IntT offset;
/* Characters from beginning */
IntT dataType; /* Text item type, e.g. FTI_String */
union {
StringT sdata; /* String if the type is FTI_String */
F_ObjHandleT idata; /* ID if item is an anchor */
} u;
} F_TextItemT;

318

FDK Programmer’s Guide

Getting text

...

M a n i p u l a t i n g Te x t

If a text item represents a string of characters, F_TextItemT.dataType
is set to FTI_String and F_TextItemT.u.sdata contains the string. If the text
item represents an anchor, F_TextItemT.dataType is set to a constant indicating
the anchor type (for example, FTI_TblAnchor) and F_TextItemT.u.idata
contains the ID of the anchored object (for example, an FO_Tbl object).
For more information on the F_TextItemsT structure, see “How the API represents
text” on page 112.
After you are finished with an F_TextItemsT structure, free the memory that it uses
with F_ApiDeallocateTextItems(). The syntax for
F_ApiDeallocateTextItems() is:
VoidT F_ApiDeallocateTextItems(F_TextItemsT *itemsp);

where itemsp is the F_TextItemsT structure that you want to free.
If you call F_ApiGetText() for a structural element (FO_Element object), the
returned information depends on the type of element, as shown in the following table:
Element’s FP_ElementType value

Information returned by F_ApiGetText()

FV_FO_CONTAINER

All the text items from the beginning to the end of the
element.

FV_FO_SYS_VAR

All the text items from the beginning to the end of the
variable.

FV_FO_XREF

All the text items from the beginning to the end of the
cross-reference.

FV_FO_FOOTNOTE

All the text items from the beginning to the end of the
footnote.

FV_FO_TBL_TITLE

All the text items from the beginning to the end of the
table title.

FV_FO_TBL_CELL

All the text items from the beginning to the end of the
cell.

FDK Programmer’s Guide 319

10

M a n i p u l a t i n g Te x t

Getting text

Element’s FP_ElementType value

Information returned by F_ApiGetText()

FV_FO_TBL_HEADING

Nothing. F_ApiGetText() fails.

FV_FO_TBL_BODY
FV_FO_TBL_FOOTING
FV_FO_MARKER
FV_FO_TBL
FV_FO_GRAPHIC
FV_FO_EQN
FV_FO_TBL_ROW

Example
The following code retrieves and prints the text in the active document’s main flow to
the console. It retrieves and prints only strings and line ends.
. . .
#include "futils.h"
F_ObjHandleT docId, flowId;
IntT i;
F_TextItemsT tis;
F_TextItemT *ip;
/* Get IDs for active document and main flow. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
flowId = F_ApiGetId(FV_SessionId, docId, FP_MainFlowInDoc);
tis = F_ApiGetText(docId, flowId, FTI_String | FTI_LineEnd);
/* Traverse text items and print strings and line ends. */
for (i=0; idataType == FTI_String)
F_Printf(NULL,"%s", ip->u.sdata);
else F_Printf(NULL,"\n");
}
F_ApiDeallocateTextItems(&tis);
. . .

320

FDK Programmer’s Guide

Getting and setting the insertion point or text selection

...

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection
The Frame API uses the document property FP_TextSelection to specify the
insertion point or text selection in a document. This property specifies a text range, or
F_TextRangeT structure, which is defined as:
typedef struct {
F_TextLocT beg; /* Beginning of the text range */
F_TextLocT end; /* End of the text range */
} F_TextRangeT;

The F_TextLocT structure, which specifies a text location (a particular point in text),
is defined as:
typedef struct{
F_ObjHandleT objId; /* Object that contains the text */
IntT offset; /* Characters from beginning */
} F_TextLocT;

If a range of text is selected, FP_TextSelection specifies a selection;
F_TextRangeT.beg and F_TextRangeT.end specify the beginning and end of
the selection. If there is an insertion point, FP_TextSelection specifies an insertion
point; F_TextRangeT.beg and F_TextRangeT.end are the same—both specify
the location of the insertion point. If there is no text selection or insertion point, the
objId and offset fields of both F_TextRangeT.beg and F_TextRangeT.end
are set to 0.
For example, suppose the first five characters of the first paragraph on the page shown
in Figure 6-1 are selected.
Subcolumns

Text frame

Figure 6-1 Page with text frame containing two subcolumns

FDK Programmer’s Guide 321

10

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection

The fields of the F_TextRangeT structure specified by the document’s
FP_TextSelection property have the following values:
Field

Value

beg.objId

ID of the first paragraph

beg.offset

0

end.objId

ID of the first paragraph

end.offset

5

If no text is selected and the insertion point is at the very beginning of the paragraph, the
fields of the F_TextRangeT structure have the following values:
Field

Value

beg.objId

ID of the first paragraph

beg.offset

0

end.objId

ID of the first paragraph

end.offset

0

..............................................................................

IMPORTANT: A valid text range can span multiple paragraphs, subcolumns, or text
frames. It can’t span multiple flows, footnotes, table cells, or text lines.
..............................................................................

It is possible for a document to have no text selection or insertion point at all. This can
occur in the following circumstances:


One or more graphic objects in the document are selected



One or more entire table cells in the document are selected



There is no selection of any type in the document

If a document has no text selection or insertion point at all, the fields of the
F_TextRangeT structure have the following values:

322

Field

Value

beg.objId

0

beg.offset

0

FDK Programmer’s Guide

Getting and setting the insertion point or text selection

Field

Value

end.objId

0

end.offset

0

...

M a n i p u l a t i n g Te x t

For more information on the different types of selection and the properties that represent
it, see “How the API represents the selection in a document” on page 80.
To get and set a document’s insertion point (or text selection), use
F_ApiGetTextRange() and F_ApiSetTextRange() to get and set its
FP_TextSelection property.
The syntax for these functions is:
F_TextRangeT F_ApiGetTextRange(F_ObjHandleT parentId,
F_ObjHandleT objId,
IntT propNum);
VoidT F_ApiSetTextRange(F_ObjHandleT parentId,
F_ObjHandleT objId,
IntT propNum,
F_TextRangeT *setVal);
This argument

Means

parentId

The ID of the object containing objId. If objId specifies a document ID,
parentId should specify FV_SessionId. If objId specifies a flow,
text frame, or table cell ID, parentId should specify the ID of the
document that contains it.

objId

The ID of the object whose property you want to get or set. To get or set the
insertion point or text selection in a document, specify the document’s ID.

propNum

The property to get or set. To get or set the insertion point or text selection in
a document, set propNum to FP_TextSelection.

setVal

The text range to which to set the property.

The beg.objId and end.objId fields of the F_TextRangeT structure returned
by F_ApiGetTextRange() always specify paragraph or text line IDs. The
beg.objId and end.objId fields of the F_TextRangeT structure that you pass
to F_ApiSetTextRange() can specify paragraph or text line IDs, but they can also
specify flow, footnote, subcolumn, table cell, or text frame IDs.

FDK Programmer’s Guide 323

10

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection

For example, to set the insertion point at the beginning of the first paragraph on the page
shown in Figure 6-1, you can use the following code:
. . .
F_ObjHandleT docId, pgfId;
F_TextRangeT tr;
. . .
/* Get document and paragraph IDs here. */
. . .
/* Create text range that specifies an insertion point. */
tr.beg.objId = tr.end.objId = pgfId;
tr.beg.offset = tr.end.offset = 0;
/* Set document’s insertion point. */
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &tr);
. . .

Instead of setting tr.beg.objId and tr.end.objId to the ID of the first
paragraph, you can set them to the ID of the A flow, the text frame, or the left
subcolumn. For example, the following code also sets the insertion point at the
beginning of the first paragraph on the page shown in Figure 6-1:
. . .
F_ObjHandleT docId, flowId;
F_TextRangeT tr;
. . .
/* Get document and flow IDs here. */
. . .
tr.beg.objId = tr.end.objId = flowId;
tr.beg.offset = tr.end.offset = 0;
/* Set document’s insertion point. */
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &tr);
. . .

324

FDK Programmer’s Guide

Getting and setting the insertion point or text selection

...

M a n i p u l a t i n g Te x t

The beg.offset and end.offset fields of the F_TextRangeT structure
returned by F_ApiGetTextRange() always specify offsets relative to the beginning
of a paragraph or text line object. The beg.offset and end.offset fields of the
F_TextRangeT structure that you pass to F_ApiSetTextRange() can specify
offsets relative to the beginning of an object, but they can also use the special value
FV_OBJ_END_OFFSET. FV_OBJ_END_OFFSET specifies the offset of the last
character in the object containing the text range. To specify offsets near the end of an
object, you can add or subtract integers from FV_OBJ_END_OFFSET. For example, the
following code selects the last five characters in a paragraph and the end of paragraph
symbol:
. . .
F_ObjHandleT docId, pgfId;
F_TextRangeT tr;
. . .
/* Get document and paragraph IDs here. */
. . .
tr.beg.objId = tr.end.objId = pgfId;
tr.beg.offset = FV_OBJ_END_OFFSET - 6;
tr.end.offset = FV_OBJ_END_OFFSET;
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &tr);
. . .

The following code selects all the text in a cell:
. . .
F_ObjHandleT docId, cellId;
F_TextRangeT tr;
. . .
/* Get document and cell IDs here. */
. . .
tr.beg.objId = tr.end.objId = cellId;
tr.beg.offset = 0;
tr.end.offset = FV_OBJ_END_OFFSET;
F_ApiSetTextRange(FV_SessionId, docId, FP_TextSelection, &tr);
. . .

FDK Programmer’s Guide 325

10

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection

Getting the text in a text range
To get the text in a specific text range, use F_ApiGetTextForRange(). The syntax
for F_ApiGetTextForRange() is:
F_TextItemsT F_ApiGetTextForRange(F_ObjHandleT docId,
F_TextRangeT *tr,
IntT flags);
This argument

Means

docId

The ID of the document containing the text range.

tr

The text range containing the text you want to get.

flags

Bit flags that specify the type of text items to retrieve. For a complete list of
the constants that represent text item types, see “F_ApiGetText()” on page
242 in the FDK Programmer’s Reference.

For example, the following code gets the selected text in the active document:
. . .
F_ObjHandleT docId;
F_TextRangeT tr;
F_TextItemsT tis;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tr = F_ApiGetTextRange(FV_SessionId, docId, FP_TextSelection);
/* If there’s just an insertion point, no text is selected. */
if(tr.beg.objId == tr.end.objId
&& tr.beg.offset == tr.end.offset) return;
tis = F_ApiGetTextForRange(docId, &tr, FTI_String);
. . .

326

FDK Programmer’s Guide

Getting and setting the insertion point or text selection

...

M a n i p u l a t i n g Te x t

Getting and setting table selections
If a table contains cells that are selected, you can get the table’s ID by querying the
document property, FP_SelectedTbl. For more information, see “Getting the IDs of
selected tables and table rows” on page 285.
If a range of text that includes several tables is selected, you can get the tables’ IDs by
calling F_ApiGetText() and retrieving the FTI_TblAnchor text items for the
selection. Each FTI_TblAnchor text item specifies the ID of a table.
To make the selection in a document include several tables, set the text selection so that
it includes the text that contains the tables’ anchors. To make the selection include
specific rows and columns within a single table, call F_ApiMakeTblSelection().
For more information, see “F_ApiMakeTblSelection()” on page 290 in the FDK
Programmer’s Reference.
Element ranges in structured tables
If the current element range is within a cell, or if it indicates a selected table part, you
can get the table's ID by querying the document property, FP_SelectedTbl. However,
it's possible for a client to set the current element range to a point between table part
elements. In this case, the document property, FP_SelectedTbl is NULL. For this
reason, you cannot always use FP_SelectedTbl to determine whether the current
element range is in a table.

FDK Programmer’s Guide 327

10

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection

If FP_SelectedTbl returns NULL, the following code determines whether the current
element location is within a table, as well as the type of the parent element:
. . .
F_ObjHandleT docId;
F_PropValT propVal;
F_ElementRangeT er;

. . .
/* Get the ID of the active document. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if(!docId) return;

er = F_ApiGetElementRange(FV_SessionId, docId,
FP_ElementSelection);

/* First check to see if there is a selected table. */
propVal = F_ApiGetPropVal(FV_SessionId, docId, FP_SelectedTbl);
if (!propVal.propVal.u.ival) {

/* Now determine whether the current element range is within a
table. */
propVal = F_ApiGetPropVal(docId, er.beg.parentId,
FP_ElementType);
if(propVal.propVal.u.ival == FV_FO_TBL) {
F_Printf(NULL,(StringT)"You are in a table\n");
} else if(propVal.propVal.u.ival == FV_FO_TBL_TITLE) {
F_Printf(NULL,(StringT)"You are in a table title\n");
} else if(propVal.propVal.u.ival == FV_FO_TBL_HEADING) {
F_Printf(NULL,(StringT)"You are in a table heading\n");
} else if(propVal.propVal.u.ival == FV_FO_TBL_BODY) {
F_Printf(NULL,(StringT)"You are in a table body\n");
} else if(propVal.propVal.u.ival == FV_FO_TBL_FOOTING) {
F_Printf(NULL,(StringT)"You are in a table footing\n");
} else if(propVal.propVal.u.ival == FV_FO_TBL_ROW) {
F_Printf(NULL,(StringT)"You are in a table row\n");
} else {

328

FDK Programmer’s Guide

Getting and setting the insertion point or text selection

...

M a n i p u l a t i n g Te x t

F_Printf(NULL,(StringT)"You are not in a table at
all\n");
}
}

/* Be sure to deallocate memory for the property value. */
F_ApiDeallocatePropVal(&propVal);

Getting and setting the structural element selection
Although you can get and set selected structural elements in a FrameMaker document
by getting and setting the text selection, it is usually easier to use the following
functions:


F_ApiGetElementRange() gets the structural element selection in a document
or book.



F_ApiSetElementRange() sets the structural element selection in a document or
book.

The syntax for these functions is:
F_ElementRangeT F_ApiGetElementRange(
F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum);
VoidT F_ApiSetElementRange(
F_ObjHandleT docId,
F_ObjHandleT objId,
IntT propNum,
F_ElementRangeT *setVal);
This argument

Means

docId

The object containing objId. To get or set the element selection in a
document, specify FV_SessionId.

objId

The ID of the document or book in which you want to get or set the element
selection.

propNum

The property to get or set. To get or set the element selection, specify
FP_ElementSelection.

setVal

The element range to set the property to.

FDK Programmer’s Guide 329

10

M a n i p u l a t i n g Te x t

Getting and setting the insertion point or text selection

The F_ElementRangeT structure is defined as:
typedef struct {
F_ElementLocT beg; /* Beginning of the element range. */
F_ElementLocT end; /* End of the element range. */
} F_ElementRangeT;

The F_ElementLocT structure specifies a location within an element. It is defined as:
typedef struct {
F_ObjHandleT parentId; /* Parent element ID. */
F_ObjHandleT childId; /* Child element ID. */
IntT offset; /* Offset within child/parent element. */
} F_ElementLocT;

For information on how FrameMaker sets the fields of the F_ElementRangeT
structure specified by FP_ElementSelection to represent different types of
selection, see “How the API represents the element selection in a structured
FrameMaker document” on page 81. For examples of how to get and set element
selections, see “F_ApiGetElementRange()” on page 175 and
“F_ApiSetElementRange()” on page 405 in the FDK Programmer’s Reference.
To traverse the selection returned by F_ApiGetElementRange(), traverse the child
elements of the element specified by beg.childId. Then traverse its sibling elements
and all of their child elements until you reach the element specified by end.childId.
To traverse an element’s child elements, you query its FP_FirstChildElement
property and then query each child element’s FP_NextSiblingElement property.
To traverse an element’s siblings, you query its FP_NextSiblingElement property
and then query each sibling element’s FP_NextSiblingElement property.

330

FDK Programmer’s Guide

Adding and deleting text

...

M a n i p u l a t i n g Te x t

Adding and deleting text
To add and delete text, use F_ApiAddText() and F_ApiDeleteText().
The syntax for these functions is:
F_TextLocT F_ApiAddText(F_ObjHandleT docId,
F_TextLocT *textLocp,
StringT text);
This argument

Means

docId

The ID of the document to which you’ll add text

textLocp

The point in text (text location) at which you’ll add text

text

The text to add

IntT F_ApiDeleteText(F_ObjHandleT docId,
F_TextRangeT *textRangep);
This argument

Means

docId

The ID of the document to delete text from

textRangep

The text range to delete

F_ApiAddText() returns the text location at the end of the text that was added.
F_ApiDeleteText() deletes any objects, such as tables and markers, anchored in
the text it deletes.
To add text to, or delete text from, a text inset, you must first unlock it by setting its
FP_TiLocked property to False. After you are done adding or deleting text, relock
the inset by setting its FP_TiLocked property to True.
To specify special characters, line breaks, or paragraph breaks when you add text, use
octal codes within the text string. For example, to specify an em dash, use \321. For
more information on special characters, see “How the API represents special
characters” on page 118. For a list of the characters in the FrameMaker product
character set and the corresponding codes, see “Character Sets” in your FrameMaker
product user documentation.

FDK Programmer’s Guide 331

10

M a n i p u l a t i n g Te x t

Adding and deleting text

Example
The following code adds some text at the insertion point (or the beginning of the current
text selection) and then deletes it. The text has a dagger (†) at the end of it.
. . .
F_TextLocT trm;
F_TextRangeT tr;
F_ObjHandleT docId;
/* Get current text selection. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tr = F_ApiGetTextRange(FV_SessionId, docId,
FP_TextSelection);
/* Return if there is no selection or IP. */
if(!tr.beg.objId) return;
/* Insert text at insertion point or beginning of selection.
* Use the octal code 240 to display the dagger.
*/
trm = F_ApiAddText(docId, &tr.beg, "Here’s some text.\240");
F_ApiAlert("Now we’ll delete it.", FF_ALERT_CONTINUE_NOTE);
/* Set tr to end at end of the added text. Then delete it. */
tr.end.offset = trm.offset;
F_ApiDeleteText(docId, &tr);
. . .

332

FDK Programmer’s Guide

Adding and deleting text

...

M a n i p u l a t i n g Te x t

Adding text to table cells
To add text to a table cell, you must first get the ID of the cell. To do this, you traverse
from the table to the row containing the cell, and then to the cell. Once you have the ID
of the cell that you want to add text to, you add text to it by calling F_ApiAddText().
The following code adds some text to the first cell in the first row of the selected table
in the active document:
. . .
F_TextLocT ip;
F_ObjHandleT docId, tblId, rowId, cellId;
/* Get the document and selected table IDs. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tblId = F_ApiGetId(FV_SessionId, docId, FP_SelectedTbl);
/* Get the ID of the first row and cell. */
rowId = F_ApiGetId(docId, tblId, FP_FirstRowInTbl);
cellId = F_ApiGetId(docId, rowId, FP_FirstCellInRow);
/* Set up text location at beginning of cell. */
ip.objId = cellId;
ip.offset = 0;
F_ApiAddText(docId, &ip, "This text appears in the cell.");
. . .

For an example of how to create a table and add text to its title, see “Creating tables” on
page 372.

FDK Programmer’s Guide 333

10

M a n i p u l a t i n g Te x t

Getting and setting text formatting

Getting and setting text formatting
Although the API doesn’t represent text as objects, the characters in text have
properties. Each character has a property list describing its font, color, condition tags,
and other character formatting attributes. The API provides special functions to get and
set the properties in this list.
You can also get and set text formatting by getting and setting paragraph, paragraph
format, and character format properties. For more information, see “Getting and setting
paragraph properties” on page 304.

Getting text properties
To get an individual property for a character, use F_ApiGetTextPropVal(). To get
the entire list of text properties for a character, use F_ApiGetTextProps().
The syntax for these functions is:
F_PropValT F_ApiGetTextPropVal(F_ObjHandleT docId,
F_TextLocT *textLocp,
IntT propNum);
F_PropValsT F_ApiGetTextProps(F_ObjHandleT docId,
F_TextLocT *textLocp);
This argument

Means

docId

The ID of the document containing the character.

textLocp

The text location of the character that you want to get text properties for. The
returned properties are the properties that apply to the character to the right
of the specified location.

propNum

The text property, such as FP_FontFamily or FP_FontSize, that you
want to get.

The API allocates the returned properties. Use F_ApiDeallocatePropVal() or
F_ApiDeallocatePropVals() to free the properties when you’re done with them.
You can get the text properties for only one character at a time, because they can be
different for each character. For more information on how the API represents characters
and text properties, see “How the API represents text” on page 112.

334

FDK Programmer’s Guide

Getting and setting text formatting

...

M a n i p u l a t i n g Te x t

Example
The following code gets the name of the character tag for the character to the right of the
insertion point:
. . .
F_TextRangeT tr;
F_PropValT prop;
F_ObjHandleT docId;
/* Get the current insertion point. */
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tr = F_ApiGetTextRange(FV_SessionId, docId, FP_TextSelection);
if(!tr.beg.objId) return;
prop = F_ApiGetTextPropVal(docId, &tr.end, FP_CharTag);
F_Printf(NULL,"The character tag is %s.\n",
prop.propVal.u.sval);
. . .

Setting text properties
To set the text properties for a text range, use F_ApiSetTextPropVal() or
F_ApiSetTextProps().
The syntax for these functions is:
VoidT F_ApiSetTextPropVal(F_ObjHandleT docId,
F_TextRangeT *textRangep,
F_PropValT *setVal);
VoidT F_ApiSetTextProps(F_ObjHandleT docId,
F_TextRangeT *textRangep,
F_PropValsT *setVal);
This argument

Means

docId

The ID of the document containing the text

textRangep

The text range

setVal

The property or property list to apply to the text range

FDK Programmer’s Guide 335

10

M a n i p u l a t i n g Te x t

Getting and setting text formatting

Applying a character format to text
To apply a character format to a text range, copy the property list of the FO_CharFmt
object that represents the character format to the text range. For example, to apply the
character format named Emphasis to the current text selection, use the following code:
. . .
F_TextRangeT tr;
F_PropValsT props;
F_ObjHandleT docId, charFmtId;
IntT i;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
if (!docId) return;
/* Get current text selection. Return if there isn’t one.*/
tr = F_ApiGetTextRange(FV_SessionId, docId,FP_ TextSelection);
if (!tr.beg.objId) return;
/* Get Emphasis properties. */
charFmtId = F_ApiGetNamedObject(docId, FO_CharFmt, "Emphasis");
props = F_ApiGetProps(docId, charFmtId);
/* Apply properties to selection. */
F_ApiSetTextProps(docId, &tr, &props);
. . .

This code has the same effect as choosing Emphasis in the Character Catalog. If no text
is selected, the code has no effect.

336

FDK Programmer’s Guide

Getting and setting text formatting

...

M a n i p u l a t i n g Te x t

Changing individual text properties
If you need to apply only an individual property to a text range, use
F_ApiSetTextProp(). For example, the following code changes the font family of
the selected text to AvantGarde:
. . .
#include "fstrings.h"
F_TextRangeT tr;
F_PropValT prop;
F_ObjHandleT docId;
UIntT i = 0;
F_StringsT strings;
docId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
tr = F_ApiGetTextRange(FV_SessionId, docId,FP_ TextSelection);
if (!tr.beg.objId) return;
/* Get list of font families available in current session. */
strings = F_ApiGetStrings(0, FV_SessionId, FP_FontFamilyNames);
/* Find index of AvantGarde in list of families in session. */
for (i=0; i

Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.6
Linearized                      : Yes
Author                          : Adobe Solution Network
Create Date                     : 2015:01:16 15:28:53Z
Keywords                        : API, FDK, C, Programming, Client, Plugin
Modify Date                     : 2015:01:16 15:29:56+05:30
Subject                         : FDK Documentation
Language                        : en
XMP Toolkit                     : Adobe XMP Core 5.4-c005 78.150055, 2012/11/19-18:45:32
Format                          : application/pdf
Title                           : FDK Programmer’s Guide
Creator                         : Adobe Solution Network
Description                     : FDK Documentation
Creator Tool                    : FrameMaker 12.0.3
Metadata Date                   : 2015:01:16 15:29:56+05:30
Producer                        : Acrobat Distiller 11.0 (Windows)
Document ID                     : uuid:ddde7987-969f-4420-be47-7c5549548360
Instance ID                     : uuid:638cba42-aa50-4d1d-8ef1-6a2da4f55932
Page Mode                       : UseOutlines
Page Count                      : 560
EXIF Metadata provided by EXIF.tools

Navigation menu