Adobe FDK Programmer’s Guide Frame Maker 7.0 Fm07 Programmers En

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

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

DownloadAdobe FDK Programmer’s Guide Frame Maker - 7.0 Fm07-fdk-programmers En
Open PDF In BrowserView PDF
FDK 7.0
Programmer’s
Guide

© 2002 Adobe Systems Incorporated. All rights reserved.
Adobe FrameMaker 7.0 User Guide for Windows, Macintosh, and UNIX
This manual, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such
license. The content of this manual is furnished for informational use only, is subject to change without notice, and should not be construed as a
commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that
may appear in this book.
Except as permitted by such license, no part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by
any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated.
Please remember that existing artwork or images that you may want to include in your project may be protected under copyright law. The
unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright owner. Please be sure to obtain
any permission required from the copyright owner.
Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to any actual organization.
Adobe, the Adobe logo, Acrobat, Acrobat Reader, Adobe Type Manager, ATM, Display PostScript, Distiller, Exchange, Frame, FrameMaker,
FrameViewer, InstantView, and PostScript are trademarks of Adobe Systems Incorporated.
Apple, PowerBook, QuickTime, Macintosh and Power Macintosh are trademarks of Apple Computer, Inc., registered in the United States and other
countries. Focoltone is a registered trademark of Gordon Phillips Limited. ImageStream Graphics Filters and ImageStream are registered trademarks
of Inso Corporation. Microsoft, MS-DOS, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in
the United States and/or other countries. Quadralay and WebWorks are registered trademarks of Quadralay Corporation. PANTONE, PANTONE
MATCHING SYSTEM, PANTONE Process Color System, and POCE are trademarks of Pantone, Inc. Proximity and Linguibase are
registered trademarks of Proximity Technology Inc. A Merriam-Webster is a registered trademark of Merriam-Webster Inc. Sun is a trademark or
registered trademark of Sun Microsystems, Inc. in the United States and other countries. TRUMATCH is a registered trademark of Trumatch Inc.
Unix is a registered trademark and X Window System is a trademark of The Open Group. Verity and TOPIC are registered trademarks of Verity,
Inc. All other trademarks are property of their respective owners.
The following are copyrights of their respective companies or organizations: Portions reproduced with the permission of Apple Computer, Inc.
© 1996 Apple Computer, Inc. Milo © 1988 Ron Avitzur PANTONE® Computer Video simulations displayed may not match PANTONE-identified
solid color standards. Use current PANTONE Color Reference Manuals for accurate color. “PANTONE Open Color Environment™ (POCE™)”
© Pantone, Inc., 1994, 1996. Pantone, Inc. is the copyright owner of “PANTONE Open Color Environment™ (POCE™)” and Software which are
licensed to Adobe to distribute for use only in combination with the Adobe Software. “PANTONE Open Color Environment™ (POCE™)” and
Software shall not be copied onto another diskette or into memory unless as part of the execution of the Adobe Software. The Spelling and Thesaurus
portions of this product are based on Proximity Linguistic Technology. The Proximity/Merriam-Webster Linguibase © 1983, 1990 MerriamWebster, Inc. C.A. Stromberg AB; Espasa-Calpe; Hachette; IDE/AS; Kruger; Lluis de Yzaguirre i Maura; Merriam-Webster Inc.; Munksgaard Int.
Publishers Ltd.; Nathan; Text & Satz Datentechnik; Van Dale Lexicographie bv; William Collins Sons & Co. Ltd.; Zanichelli. All rights reserved.
Color Database © Dainippon Ink & Chemicals, Inc., licensed to Adobe. Outside In® Viewer Technology, 1992-1996 Inso Corporation; Image
Stream® Graphics and Presentation Filters, 1992-1996 Inso Corporation. All rights reserved. TRUMATCH 4-Color Selector © 1992 Trumatch, Inc.
All rights reserved. Portions copyrighted for the FrameViewer Retrieval Tools © 1988-1995 Verity, Inc. All rights reserved.
APPLE COMPUTER, INC. (“APPLE”) MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE
SOFTWARE. APPLE DOES NOT WARRANT, GUARANTEE, OR MAKE ANY REPRESENTA-TIONS REGARDING THE USE OR THE
RESULTS OF THE USE OF THE APPLE SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY, CURRENTNESS,
OR OTHERWISE. THE ENTIRE RISK AS TO THE RESULTS AND PERFORMANCE OF THE APPLE SOFTWARE IS ASSUMED BY YOU.
THE EXCLUSION OF IMPLIED WARRANTIES IS NOT PERMITTED BY SOME STATES. THE ABOVE EXCLUSION MAY NOT APPLY
TO YOU.
IN NO EVENT WILL APPLE, ITS DIRECTORS, OFFICERS, EMPLOYEES, OR AGENTS BE LIABLE TO YOU FOR ANY
CONSEQUENTIAL, INCIDENTAL, OR INDIRECT DAMAGES (INCLUDING DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
INTERRUPTION, LOSS OF BUSINESS INFORMATION, AND THE LIKE) ARISING OUT OF THE USE OR INABILITY TO USE THE
APPLE SOFTWARE EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES DO
NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
LIMITATIONS MAY NOT APPLY TO YOU.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA
Notice to U.S. government end users. The software and documentation are “commercial items,” as that term is defined at 48 C.F.R. §2.101,
consisting of “commercial computer software” and “commercial computer software documentation,” as such terms are used in 48 C.F.R. §12.212
or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through 227.7202-4, as applicable, the
commercial computer software and commercial computer software documentation are being licensed to U.S. government end users (A) only as
commercial items and (B) with only those rights as are granted to all other end users pursuant to the terms and conditions set forth in the Adobe
standard commercial agreement for this software. Unpublished rights reserved under the copyright laws of the United States.

ii

FDK Programmer’s Guide

Contents

Using Frame Developer Tools . . . . . . . . . . . . . . . . . . . . . . . ix
The Frame Developer’s Kit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
Other FrameMaker features for developers . . . . . . . . . . . . . . . . . . . . . . . . . . x
Choosing the right Frame tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
FDK documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Naming conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii
Style conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

Part I: Frame Application Program Interface (API)
Chapter 1

Introduction to the Frame API . . . . . . . . . . . . . . . . 3

How the API works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Special types of clients. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Portability. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Running clients with different FrameMaker product interfaces . . . . . . . . . . . . . . . . . 6
Creating and running a client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
A simple example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Chapter 2

API Client Initialization . . . . . . . . . . . . . . . . . . . 13

Responding to the FrameMaker product’s initialization call . . . . . . . . . . . . . . . . . 13
Initialization types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Disabling the API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Chapter 3

Creating Your Client’s User Interface . . . . . . . . . . . . 17

Using API dialog boxes to prompt the user for input . . . . . . . . . . . . . . . . . . . . . 17
Using commands, menu items, and menus in your client . . . . . . . . . . . . . . . . . . 24
Replacing FrameMaker product menus and commands . . . . . . . . . . . . . . . . . . . 30
Allowing users to configure your client’s interface . . . . . . . . . . . . . . . . . . . . . . 30
Using hypertext commands in your client’s user interface . . . . . . . . . . . . . . . . . . 31

FDK Programmer’s Guide

iii

Responding to user-initiated events or FrameMaker product operations . . . . . . . . . . 34
Implementing quick keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Freeing system resources by bailing out . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Chapter 4

Executing Commands with API Functions

. . . . . . . . . 45

Handling errors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Handling messages and warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Opening documents and books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Creating documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Printing documents and books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Saving documents and books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Closing documents and books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Quitting a Frame session. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Comparing documents and books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Updating and generating documents and books . . . . . . . . . . . . . . . . . . . . . . . 70
Simulating user input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Straddling table cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Executing Structured FrameMaker commands . . . . . . . . . . . . . . . . . . . . . . . 76

Chapter 5

Getting and Setting Properties . . . . . . . . . . . . . . . 81

What you can do with object properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Getting the IDs of the objects you want to change . . . . . . . . . . . . . . . . . . . . . . 82
Manipulating properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Getting and setting session properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Getting and setting document properties . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Getting and setting graphic object properties . . . . . . . . . . . . . . . . . . . . . . . . 99
Getting and setting paragraph properties . . . . . . . . . . . . . . . . . . . . . . . . . .102
Getting and setting book properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . .105
Getting and setting FrameMaker properties . . . . . . . . . . . . . . . . . . . . . . . . .105

Chapter 6

Manipulating Text . . . . . . . . . . . . . . . . . . . . . 111

Getting text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .111
Getting and setting the insertion point or text selection . . . . . . . . . . . . . . . . . . .114
Adding and deleting text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .121

iv

FDK Programmer’s Guide

Getting and setting text formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123
Executing Clipboard functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .127

Chapter 7

Manipulating Asian Text . . . . . . . . . . . . . . . . . . 131

Creating a rubi group. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .131
Text encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .132
Using encoding data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .134
Inspecting and manipulating encoded text . . . . . . . . . . . . . . . . . . . . . . . . . .138
Parsing an encoded string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .139
Getting the encoding for a text item . . . . . . . . . . . . . . . . . . . . . . . . . . . . .140
Special issues with double byte encodings . . . . . . . . . . . . . . . . . . . . . . . . .140

Chapter 8

Creating and Deleting API Objects . . . . . . . . . . . . 143

Creating objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .143
Deleting objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .158
Implicit property changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .160

Chapter 9

Manipulating Commands and Menus with the API

. . . . 161

How the API represents commands and menus . . . . . . . . . . . . . . . . . . . . . . .161
Getting the IDs of commands and menus . . . . . . . . . . . . . . . . . . . . . . . . . .163
Determining a session’s menu configuration. . . . . . . . . . . . . . . . . . . . . . . . .164
Arranging menus and menu items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .166
Getting and setting menu item labels . . . . . . . . . . . . . . . . . . . . . . . . . . . .170
Manipulating expandomatic menu items . . . . . . . . . . . . . . . . . . . . . . . . . . .172
Using check marks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .173
Using context-sensitive commands and menu items . . . . . . . . . . . . . . . . . . . .173
Providing context-sensitive Help for client menu items . . . . . . . . . . . . . . . . . . .175

Chapter 10

Creating Custom Dialog Boxes for Your Client . . . . . . 177

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .177
How to create a dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .185
Creating a DRE file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .185
Designing the layout of the dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . .189
Setting the properties of the dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . .193
Setting the properties of a dialog item . . . . . . . . . . . . . . . . . . . . . . . . . . . .197

FDK Programmer’s Guide

v

Saving a DRE file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .204
Testing a dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .205
A simple example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .206
General tips for dialog editing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .209
Summary of keyboard shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .209

Chapter 11

Handling Custom Dialog Box Events . . . . . . . . . . . 211

How the API represents dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . .211
Overview of using a custom dialog box in your client . . . . . . . . . . . . . . . . . . . .214
Opening dialog resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .217
Initializing items in a dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .218
Displaying a dialog box. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .219
Updating items in a dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .220
Handling user actions in dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . .221
Closing a dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .227

Chapter 12

Using Imported Files and Insets

. . . . . . . . . . . . . 229

Types of imported files and insets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .229
Importing text and graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .230
Updating text insets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .235
Client text insets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .236
Writing filter clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .239
Specifying format IDs and filetype hint strings . . . . . . . . . . . . . . . . . . . . . . . .247
Associating a file format with signature bytes . . . . . . . . . . . . . . . . . . . . . . . .255
Writing graphic inset editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .256

Part II: Frame Product Architecture
Chapter 13

Frame Session Architecture . . . . . . . . . . . . . . . . 269

Identifying objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .269
Representing object characteristics with properties . . . . . . . . . . . . . . . . . . . . .270
FrameMaker product sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .274

vi

FDK Programmer’s Guide

Chapter 14

Frame Document Architecture . . . . . . . . . . . . . . . 279

Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .279
Global document information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284
Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .288
Graphic objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .293
Flows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .297
Paragraph Catalog formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .300
Paragraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .302
Character Catalog formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .305
Condition Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .309
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .311
Markers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .319
Cross-reference formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .322
Cross-references . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .323
Variable formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .324
Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .326
Footnotes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .327
Ruling Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .328
Table Catalog formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .330
Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .332
Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .338
Structural element definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .342
Format rules and format rule clauses . . . . . . . . . . . . . . . . . . . . . . . . . . . .344
Format change lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .346
Structural elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .347

Chapter 15

Frame Book Architecture . . . . . . . . . . . . . . . . . 351

What the user sees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .351
How the API represents books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .351
Creating new books and components . . . . . . . . . . . . . . . . . . . . . . . . . . . .355
Updating a book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .356
Using the book error log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .360

FDK Programmer’s Guide

vii

Part III: Frame Development Environment (FDE)
Chapter 16

Introduction to FDE . . . . . . . . . . . . . . . . . . . . 365

How the FDE works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .365
How to make your client portable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .366
A simple FDE filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .370

Chapter 17

Making I/O and Memory Calls Portable . . . . . . . . . . 375

Initializing the FDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .375
Using platform-independent representations of pathnames . . . . . . . . . . . . . . . . .375
Making I/O portable with channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .377
Assertion-handler functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .378
Making memory allocation portable . . . . . . . . . . . . . . . . . . . . . . . . . . . . .378
Error and progress reporting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .379

Chapter 18

FDE Utility Libraries . . . . . . . . . . . . . . . . . . . . 381

String library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .381
The string list library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .382
Character library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .382
The I/O library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .382
The hash library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .383
Metric library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .384
MIF data structures and macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .384
The MIF library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385
Simple MIF library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .387

viii

FDK Programmer’s Guide

Using Frame Developer Tools

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 everything 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

●

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

FDK Programmer’s Guide

ix

Using Frame Developer Tools

FDE
The Frame Development Environment (FDE) helps you make your client portable to all
platforms supported by FrameMaker. It 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. Frame
encourages you to use the FDE to develop all your clients. The FDE includes header files and
libraries for each supported platform.

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
(XML or SGML).

Other FrameMaker 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:
●

Sharing files with earlier releases of FrameMaker products

●

Converting database files into Frame documents

●

Filtering word processor documents into Frame documents

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

fmbatch
The fmbatch utility is shipped with UNIX versions of FrameMaker. It allows you to open,
print, reformat, and save FrameMaker product files without displaying them. You can use
fmbatch directly at a UNIX graphics workstation or in a remote shell from a nongraphics
terminal. The fmbatch utility provides interactive and batch modes. When you use it in batch

x

FDK Programmer’s Guide

Using Frame Developer Tools

mode, you can execute operations on multiple files automatically. For example, you can use
fmbatch for:
●

Printing books or documents from a remote location

●

Printing multiple books or documents automatically

●

Updating multiple books or documents automatically

●

Converting multiple books or documents to MIF

For more information on the fmbatch utility, see the FrameMaker product user
documentation for UNIX platforms.

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 or UNIX shell
script. 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

fmbatch

Doesn’t require C programming; can be used remotely from
a nongraphics terminal

Only provides simple
functions; only
available on UNIX
platforms

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.

FDK Programmer’s Guide

xi

Using Frame Developer Tools

FDK Platform Guide
The FDK Platform Guide is printed in several versions, each describing how to install the
FDK on a specific platform. It provides the pathnames of sample programs and describes
platform-specific differences in using the FDK.

FDK Programmer’s Guide
The FDK Programmer’s Guide describes how to use the FDK to create clients for
FrameMaker. To get the most from this manual, you should be familiar with the C
programming language and event-driven programming.
The FDK Programmer’s Guide is divided into three parts:
●

Part I, Frame Application Program Interface (API), provides instructions for creating API
clients.

●

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

●

Part III, Frame Development Environment (FDE), provides instructions for making filters
and API clients platform-independent.

FDK Programmer’s Reference
The FDK Programmer’s Guide, which you are reading now, provides FDK reference
information, such as error codes and data structure, function, and property descriptions.

Structure Import/Export API Programmer’s Guide
The Structure Import/Export API Programmer’s Guide provides instructions and reference
information for using the Structure Import/Export API.

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:

xii

Type

Naming convention

Example

API error codes

Begin with FE_

FE_NotPgf

API functions

Begin with F_Api

F_ApiGetInt()

API scriptable function
property names

Begin with FS_

FS_NewDoc

FDE functions

Begin with F_

F_StrNew()

FDK Programmer’s Guide

Using Frame Developer Tools

Type

Naming convention

Example

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. (In earlier versions you could
specify which FrameMaker products would initialize your client; FrameMaker,
FrameMaker+SGML, or FrameViewer.)
The FDK Programmer’s Reference indicates those FDK functions that apply only to structured
FrameMaker documents, as follows:

FDK Programmer’s Guide

xiii

Using Frame Developer Tools

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.

Pathnames
Code examples in this manual use UNIX pathnames. For example:
docId = F_ApiSimpleOpen((StringT)"/tmp/mydoc.fm", False);

If you are using the FDK on the Macintosh or on Windows, change the code to use the
filepath naming conventions for those platforms. For example, on Macintosh, change the code
above to code like the following:
docId = F_ApiSimpleOpen((StringT)"MyHardDrive:tmp:mydoc.fm", False);

On Windows, change it to code like the following:
docId = F_ApiSimpleOpen((StringT)"c:\\tmp\\mydoc.fm", False);

The FDK provides functions for converting platform-specific filepaths. For more information,
see “Making I/O portable with channels” on page 377 of the FDK Programmer’s Guide.

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);

xiv

FDK Programmer’s Guide

Part I
Frame Application Program Interface
(API)

FDK Programmer’s Guide

1

2

FDK Programmer’s Guide

1

Introduction to the Frame API

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 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.
TABLE 1.1
Property

Data Type

Value

FP_Width

MetricT

20 * 65536a

FP_Height

MetricT

10 * 65536

FP_RectangleIsSmoothed

IntT

True

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

3

1

Introduction to the Frame API

TABLE 1.1
Property

Data Type

Value

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 675 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” in the FDK Programmer’s Reference.

How clients can change FrameMaker 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.

●

Programmatically executing FrameMaker product commands, such as Open, Print, Save,
and Clear All Change Bars

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 use different mechanisms to work with FrameMaker on the different platforms the
FDK supports. On the Macintosh, clients are dynamically loaded modules. On Windows, they
are dynamic link libraries (DLLs), or they can be executable programs that use COM to
communicate with a FrameMaker session. On UNIX platforms, they can be either dynamically

4

FDK Programmer’s Guide

Introduction to the Frame API

1

linked code or separate processes that use the RPC mechanism to communicate with the
FrameMaker product. 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 the FrameMaker product 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. For
more information on sample programs provided with the FDK, see the FDK Platform Guide
for the platform you’re using.

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 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.

FDK Programmer’s Guide

5

1

Introduction to the Frame API

Take-control clients
A take-control client is a client that takes control of a FrameMaker product session
immediately after the FrameMaker product starts. The UNIX implementation of the FDK
allows users to specify a take-control client in the FrameMaker product command line. Takecontrol 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,” in the FDK Programmer’s Reference.
Due to platform limitations Asynchronous clients (clients that run outside of the FrameMaker
process space) are not portable on all platforms. For specific information on Asynchronous
clients see the FDK Platform guide for the platform in question.

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,” in the FDK Programmer’s Reference. For an example of how to
programmatically determine which product interface is running, see ‘‘F_ApiGetString()’’ on
page 158 of the FDK Programmer’s Reference.

Creating and running a client
To create and run a client, follow these general steps:

6

FDK Programmer’s Guide

Introduction to the Frame API

1

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().
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.

FDK Programmer’s Guide

7

1

Introduction to the Frame API

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.
●

On UNIX platforms, when you start FrameMaker it looks for a text-only file named
fminit/UILanguage/APIArea/apiclients, where UILanguage is the user interface
language (such as usenglish for US English). It looks in the directory from which it
was started, in your home directory, and in $FMHOME. To register your client, create an
fminit/UILanguage/APIArea/apiclients file in your home directory or the
directory from which you intend to start the FrameMaker product. Add the following lines
to the file:



>

The path clientdir specifies the full path of the directory containing your client’s executable
file and other resources, client_name is the name that FrameMaker and other clients use to
reference your client, and executable_name is the name of your client’s executable file. The
FDK sets the environment variable $FAPIDIR to clientdir.
●

On Macintosh computers, copy or move your client to the FrameMaker product’s Modules
folder.

●

On Windows platforms, 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, Standard, DocReport, or
TextImport. description is a string describing your client. path is the pathname of your

8

FDK Programmer’s Guide

Introduction to the Frame API

1

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.
For information on registering your client on a specific platform, see the FDK Platform Guide
for that platform.

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.
31.
32.
33.
34.

FDK Programmer’s Guide

#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;
/* 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. */

9

1

Introduction to the Frame API

35. switch (command)
36.
{
37.
case CloseDoc:
/* Close document even if it’s changed. */
38.
F_ApiClose(docId, FF_CLOSE_MODIFIED);
39.
break;
40.
41.
case SetFill:
/* Set fill pattern to black. */
42.
/* Get ID of selected object. */
43.
objId = F_ApiGetId(FV_SessionId, docId,
44.
FP_FirstSelectedGraphicInDoc);
45.
46.
/* If an object is selected, set its fill. */
47.
if (!objId) F_ApiAlert("Select an object first.",
48.
FF_ALERT_CONTINUE_WARN);
49.
else F_ApiSetInt(docId, objId, FP_Fill, FV_FILL_BLACK);
50.
break;
51.
52.
case AddPage:
/* Add a new page. */
53.
pgId = F_ApiNewSeriesObject(docId, FO_BodyPage, 0);
54.
break;
55.
}
56. }

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).
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

10

FDK Programmer’s Guide

Introduction to the Frame API

1

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.
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 143.

FDK Programmer’s Guide

11

1

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 the
samples/myapi directory of your FDK installation. For the location of the files, see the FDK
Platform Guide for your platform. To compile the client, use your platform’s make or build
utility.
To run the example client, you must first register it as required by your platform’s
implementation of the API:
●

If you are working on a UNIX platform with US English as the user interface language, and
the pathname of your compiled client is /usr/fdk/samples/ch1/fa.myapi, you can
register it by creating a text-only file named
~/fminit/usenglish/APIArea/apiclients with the following lines in it:



>

When you start the FrameMaker product, it reads this file and starts the fa.myapi client.
●

If you are working on a Macintosh computer, copy or move the example client to the
FrameMaker product’s Modules folder.

●

If you are working on a Windows platform and 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,all

For more information on how to register clients, see the FDK Platform Guide.
After you have registered the example client, start the FrameMaker product and open a
document. The API menu should appear to the right of the FrameMaker product menus.

12

FDK Programmer’s Guide

2

API Client Initialization

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 */
}
TABLE 2.1
This argument

Means

initialization

A flag that indicates the type of initialization (see “Initialization
types” on page 14)

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.”
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);
}
. . .

1. For information on registering your client with the FrameMaker product, see the FDK Platform Guide for your platform.

FDK Programmer’s Guide

13

2

API Client Initialization

Initialization types
The following table summarizes the different types of initializations and the
initialization constants FrameMaker can pass to your client’s F_ApiInitialize()
callback.
TABLE 2.2
Type of
initialization

When F_ApiInitialize
is called

Initialization constant

Clients that receive
initialization

FrameMaker starts
After starting
with no special options

FA_Init_First

All except document
reports and filters

FrameMaker 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_TakeControl

All clients set up as takecontrol clients

FA_Init_First
initialization
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

First initialization
When the user starts the FrameMaker product, the 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 take-control 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.

14

FDK Programmer’s Guide

API Client Initialization

2

On UNIX platforms, the FrameMaker product issues the FA_Init_TakeControl
initialization to only one client. The user specifies this client by starting the FrameMaker
product with the -apiclient client_name option (where client_name is the
registered name of the client).
On Windows and Macintosh platforms, the FrameMaker product can issue the
FA_Init_TakeControl initialization to several clients. To set up a client to receive
FA_Init_TakeControl initializations on Windows, set the client’s type to TakeControl
in the FrameMaker product .ini file. To set up a client to receive FA_Init_TakeControl
initializations on the Macintosh, set the flags field of the client’s fdat resource to include
ApiClientFlagCanTakeControl. For more information on setting up clients to receive
take-control initializations, see the FDK Platform Guide for your platform.

Document report initialization
When the 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 34.
To receive notification, your filter must be registered as a filter. For information on registering
filters, see the FDK Platform Guide for your platform.

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.

FDK Programmer’s Guide

15

2

API Client Initialization

For more information on F_ApiBailOut(), see ‘‘F_ApiBailOut()’’ on page 48 of the FDK
Programmer’s Reference.

Disabling the API
The user can disable all API clients before starting the FrameMaker product. On UNIX
platforms, the user can disable all clients by specifying -noapi in a resource file or when
starting the FrameMaker product from the command line. On Windows platforms, the user can
disable all clients by changing the API=On setting in the maker.ini file to API=Off. On
the Macintosh, the user can disable clients by dragging them from the FrameMaker product
Modules folder. For more information on disabling individual clients, see the FDK Platform
Guide for your platform.
IMPO RTAN T:

16

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.

FDK Programmer’s Guide

3

Creating Your Client’s User
Interface
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”

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

FDK Programmer’s Guide

17

3

Creating Your Client’s User Interface

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.
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);

18

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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.

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 675 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.
IMPO RTAN T:

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. For more information on
F_ApiDeallocateString(), see ‘‘F_ApiDeallocateStructureType()’’ on
page 74 of the FDK Programmer’s Reference.

Examples

The following code displays the dialog box shown in Figure 3.2:

FDK Programmer’s Guide

19

3

Creating Your Client’s User Interface

. . .
#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

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);
. . .

20

FDK Programmer’s Guide

Creating Your Client’s User Interface

FIGURE 3.4

3

Metric prompt dialog box

Using file selection dialog boxes
To display dialog boxes similar to the FrameMaker 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);
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 53 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.

IMPO RTAN T:

F_ApiChooseFile() allocates memory for the string referenced by
*choice. Use F_ApiDeallocateString() to free the string when you
are done with it.

Example

To create the dialog box shown in Figure 3.5, add the following code to your client:

FDK Programmer’s Guide

21

3

Creating Your Client’s User Interface

. . .
#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

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);

22

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.

FDK Programmer’s Guide

Creating Your Client’s User Interface

This argument

Means

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.

3

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.
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);
}
. . .

FDK Programmer’s Guide

23

3

Creating Your Client’s User Interface

FIGURE 3.6

Scroll list dialog box

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 screen on a Macintosh, at the top of a document or book window on UNIX
platforms, and at the top of the FrameMaker product 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);

24

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.

FDK Programmer’s Guide

Creating Your Client’s User Interface

This argument

Means

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.

3

The menu and command names you can specify for objName depend on the FrameMaker
product and how the user has customized the menus. On UNIX platforms, the default
command names are listed in $FMHOME/fminit/UILanguage/configui/Commands and
the default menu names are listed in
$FMHOME/fminit/UILanguage/configui/ProductInterfaceMenus, where
UILanguage represents the user-interface language (such as usenglish for US English) and
ProductInterface is the name of the product interface (either maker or structured). For
information on where the menus are listed on other platforms, see the FDK Platform Guide for
your platform.
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.
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

FDK Programmer’s Guide

25

3

Creating Your Client’s User Interface

FrameMaker product menu bar

Name

View-only menu bar

!ViewOnlyMainMenu

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.
IMPO RTAN T:

26

To ensure that your client is portable to the different platforms that
FrameMaker supports, specify only shortcuts that begin with Esc. On UNIX,
the Esc shortcut appears on the menu next to the menu item label. On the
Macintosh or Windows, the shortcut does not appear. However, the user can
still execute it. For example, if you specify \\!xy for the keyboard shortcut,
the user can execute the command from the keyboard by pressing Esc x y. For

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

more information on specifying keyboard shortcuts, see the sections of your
user documentation that discuss the FrameMaker product’s configurable user
interface.
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");
. . .

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.
IMPO RTAN T:

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

FDK Programmer’s Guide

27

3

Creating Your Client’s User Interface

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");
. . .
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.7

28

Edit menu with a client-defined pull-right menu

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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
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;
}
}

FDK Programmer’s Guide

29

3

Creating Your Client’s User Interface

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.
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 gives 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

30

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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.
IMPO RTAN T:

Adobe Systems recommends that you document the names of your client’s
menus and commands so that users can customize them.

For more information on using menu configuration files, see the online manual, Customizing
FrameMaker. 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. The
basic set of FrameMaker hypertext commands allows you to establish links within and
between documents and to jump from link to link.
You can lock a FrameMaker 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 578 of the FDK
Programmer’s Reference.
FrameMaker provides 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.

FDK Programmer’s Guide

31

3

Creating Your Client’s User Interface

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.

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.
On UNIX platforms, it is the name specified in the  statement in the
apiclients file. On the Macintosh, it is the name of the client file in the
Modules folder. On Windows, it is the ClientName specified in the
[APIClients] section of the maker.ini file. For more information
on registering FDK clients, see the FDK Platform Guide for your platform.

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. */
}

32

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

Creating Your Client’s User Interface

3

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.8.

FIGURE 3.8

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.
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);

FDK Programmer’s Guide

33

3

Creating Your Client’s User Interface

/* 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.

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:

34

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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.

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 226 of
the FDK Programmer’s Reference.
You can request notification in your client’s F_ApiInitialize() callback or anywhere
you want in your client.
Example

Suppose you want the 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:

FDK Programmer’s Guide

35

3

Creating Your Client’s User Interface

. . .
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

File-to-file

FA_Note_FilterFileToFile

For more information on writing client filters, see “Writing filter clients” on page 239. For
more information on registering filters, see the FDK Platform Guide for your platform.

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. */
}

36

This argument

Means

notification

A constant that indicates the event and the notification point (see the table on
page 35 for a list of some 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.

FDK Programmer’s Guide

Creating Your Client’s User Interface

This argument

Means

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.

3

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.
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.
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:

FDK Programmer’s Guide

37

3

Creating Your Client’s User Interface

. . .
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.
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

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.
IMPO RTAN T:

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 another 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)

38

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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

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.
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:

FDK Programmer’s Guide

39

3

Creating Your Client’s User Interface

. . .
#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

FrameMaker 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.
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;
{

1. An API client can explicitly instruct the 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 138 and
‘‘F_ApiGetSaveDefaultParams()’’ on page 152 of the FDK Programmer’s Reference.

40

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

/* 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.
Handling notification for Open operations

The Open operation is more complex than most other operations. 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

FDK Programmer’s Guide

41

3

Creating Your Client’s User Interface

selected it but before the FrameMaker product has checked its type, you should request
notification for the FA_Note_PreFileType notification point.
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 provides 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.
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);

42

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

FDK Programmer’s Guide

Creating Your Client’s User Interface

3

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.9:
. . .
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.9

Tag area with client-defined quick key

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. If
your client is a dynamically linked client on a UNIX platform, bailing out has no effect.
IMPO RTAN T:

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

FDK Programmer’s Guide

43

3

Creating Your Client’s User Interface

FrameMaker product also calls the appropriate callback function for the menu choice,
hypertext command, or event.
IMPO RTAN T:

If your client bails out, it loses all its global variable settings.

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);
}

44

FDK Programmer’s Guide

4

Executing Commands with API
Functions
This chapter discusses how to use Frame API functions to execute FrameMaker 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 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.

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,

FDK Programmer’s Guide

45

4

Executing Commands with API Functions

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.

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);

46

FDK Programmer’s Guide

Executing Commands with API Functions

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.

4

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.
Example

The following code opens a document named /tmp/my.doc1 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);
}
. . .
1. Examples in this manual use UNIX pathnames. For information on specifying pathnames on other platforms, see the FDK
Platform Guide for that platform.

FDK Programmer’s Guide

47

4

Executing Commands with API Functions

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 270 and “Manipulating property lists directly” on page 93.
The syntax for F_ApiOpen() is:
F_ObjHandleT F_ApiOpen(StringT fileName,
F_PropValsT *openParamsp,
F_PropValsT **openReturnParamspp);
This argument

Means
The absolute pathname of the file to open. If you are using

fileName

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.

IMPO RTAN T:

Always initialize the pointer to the property list that you specify for
openReturnParamspp to NULL before you call F_ApiOpen().

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.

48

FDK Programmer’s Guide

Executing Commands with API Functions

4

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 138 of 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.
Setting this property on Macintosh platforms has no effect.
NULL.

FS_NewDoc

Create a new document.

False: open an existing document.
True: create a new document.
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();

FDK Programmer’s Guide

49

4

Executing Commands with API Functions

/* 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 138 of 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.
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;

50

FDK Programmer’s Guide

Executing Commands with API Functions

4

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.
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
A string that specifies the opened file’s pathname. If you scripted

FS_OpenedFileName

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.
The error condition. If the file is opened successfully, it is set to

FS_OpenNativeError

FE_Success. For a complete list of the other values it can be set
to, see ‘‘F_ApiOpen()’’ on page 238 of the FDK Programmer’s
Reference.
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 238 of the FDK Programmer’s Reference.

FS_OpenStatus

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

51

4

Executing Commands with API Functions

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 console on UNIX platforms, the error log window on the
Macintosh, and the Frame console on Windows. F_ApiPrintOpenStatus() is useful for
debugging clients that use F_ApiOpen(). For more information, see
‘‘F_ApiPrintOpenStatus()’’ on page 250 of 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);
This argument

Means

pvp

The property list

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 scrip

52

FDK Programmer’s Guide

Executing Commands with API Functions

4

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);
. . .

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 146. 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);

FDK Programmer’s Guide

53

4

Executing Commands with API Functions

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.
IMPO RTAN T:

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
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” on
page 55.

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 59
. . .
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);
. . .

54

FDK Programmer’s Guide

Executing Commands with API Functions

4

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 279.
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);
This argument
width

Means
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.

FDK Programmer’s Guide

55

4

Executing Commands with API Functions

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.
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 48.
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.

56

FDK Programmer’s Guide

Executing Commands with API Functions

4

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 59 for syntax. */
F_ApiSimpleSave(docId, "/tmp/mynew.doc", False);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .
IMPO RTAN T:

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().

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

FDK Programmer’s Guide

57

4

Executing Commands with API Functions

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 saves 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 561 of 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);
. . .

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);
. . .

58

FDK Programmer’s Guide

Executing Commands with API Functions

4

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.

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.
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:

FDK Programmer’s Guide

59

4

Executing Commands with API Functions

. . .
#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) and the UNIX file permissions. 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.
The syntax for F_ApiSave() is:
F_ObjHandleT F_ApiSave(F_ObjHandleT docId,
StringT saveAsName,
F_PropValsT *saveParamsp,
F_PropValsT **saveReturnParamspp);

60

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.

FDK Programmer’s Guide

Executing Commands with API Functions

This argument

Means

saveReturnParamspp

A property list that returns information about how the FrameMaker
product saved the file.

IMPO RTAN T:

4

Always initialize the pointer to the property list that you specify for
saveReturnParamspp to NULL before you call F_ApiSave().

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.
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.

FDK Programmer’s Guide

61

4

Executing Commands with API Functions

Property

Meaning and possible values

FS_FileType

Specifies the type of file to save to
FV_SaveFmtBinary: save in Frame binary format for this
version of FrameMaker.
FV_SaveFmtBinary60: save in binary format for
FrameMaker 6.0
FV_SaveFmtInterchange: save as MIF.
FV_SaveFmtStationery: save in Stationery format
(Macintosh only).
FV_SaveFmtViewOnly: save in View Only format
FV_SaveFmtSgml: save in SGML format.
FV_SaveFmtText: save in Text Only format.
FV_SaveFmtXml: save in XML format.
FV_SaveFmtPdf: save as PostScript, and then invoke
Acrobat Distillera to create a PDF version of the document.
This is the same as choosing PDF from the Format popup
menu in the Save As dialog box.

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
a. Note: This will only work if the Acrobat Distiller software is installed on the system.

For the complete property list returned by F_ApiGetSaveDefaultParams(), see
‘‘F_ApiGetSaveDefaultParams()’’ on page 152 of the FDK Programmer’s Reference.
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. */

62

FDK Programmer’s Guide

Executing Commands with API Functions

4

mydocId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
/* Get default property list. */
params = F_ApiGetSaveDefaultParams();

FDK Programmer’s Guide

63

4

Executing Commands with API Functions

/* 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.
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 returnParamspp. This property list
provides information on how the FrameMaker product saved the file. It includes the properties
shown in the following table.

64

FDK Programmer’s Guide

Executing Commands with API Functions

Property

Meaning and Possible Values

FS_SavedFileName

A string that specifies the saved file’s pathname.

FS_SaveNativeError

4

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 272 of 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 272 of 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(). For
example, the following code determines if a Save operation was canceled because the current
FrameMaker document was already open:
. . .
F_PropValsT params, *returnParamsp = NULL;
F_ObjHandleT mydocId;
/* Get the ID of the active document. */
mydocId = F_ApiGetId(0, FV_SessionId, FP_ActiveDoc);
params = F_ApiGetSaveDefaultParams();
F_ApiSave(mydocId, "/tmp/my.doc", ¶ms, &returnParamsp);
if (F_ApiCheckStatus(returnParamsp, FV_FileWasInUse))
F_ApiAlert("Save cancelled - file is in use",FF_ALERT_CONTINUE_NOTE);
/* Deallocate property lists. */
F_ApiDeallocatePropVals(¶ms);
F_ApiDeallocatePropVals(returnParamsp);
. . .

The API provides a utility function named F_ApiPrintSaveStatus(), which prints the
save error values to the console on UNIX platforms, the FrameMaker console on Windows,
and the error log window on the Macintosh. For more information, see
‘‘F_ApiPrintSaveStatus()’’ on page 253 of the FDK Programmer’s Reference.
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.

FDK Programmer’s Guide

65

4

Executing Commands with API Functions

. . .
#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);
. . .

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);

66

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.

FDK Programmer’s Guide

Executing Commands with API Functions

4

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.
IMPO RTAN T:

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).

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);
. . .

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 66.
For example, to close all the open documents and books in the current Frame session, and quit
the session, use the following code:

FDK Programmer’s Guide

67

4

Executing Commands with API Functions

. . .
F_ApiClose(FV_SessionId, FF_CLOSE_MODIFIED);
. . .

Because 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 the 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);
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.

replaceText

Text to appear in place of the deleted text. For no replacement text,
specify NULL.

compareThreshold

If zero, the compare function uses the default value of 75.
If not zero, the the function uses the setting in the FrameMaker
configuratin files.
Threshold expresses the 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.

The F_CompareRetT structure is defined as:

68

FDK Programmer’s Guide

Executing Commands with API Functions

4

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.

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);
. . .

FDK Programmer’s Guide

69

4

Executing Commands with API Functions

FIGURE 4.2

Specifications for Compare Documents

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 270 and “Manipulating property lists directly” on
page 93.
The syntax for F_ApiUpdateBook() is:
ErrorT F_ApiOpen(F_ObjHandleT bookId,
F_PropValsT *updateParamsp,
F_PropValsT **updateReturnParamspp);

70

FDK Programmer’s Guide

Executing Commands with API Functions

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.

IMPO RTAN T:

4

Always initialize the pointer to the property list that you specify for
openReturnParamspp to NULL before you call F_ApiUpdateBook().

If F_ApiUpdateBook() is successful, it returns FE_Success. Otherwise, it returns an
error which has the same value as FA_errno.
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);

FDK Programmer’s Guide

71

4

Executing Commands with API Functions

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().
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.

72

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

FDK Programmer’s Guide

Executing Commands with API Functions

This value

Means

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

4

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.
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 FDK Programmer’s Reference
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.
*/

FDK Programmer’s Guide

73

4

Executing Commands with API Functions

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);
}
. . .

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 FrameMaker, it executes each f-code as if the
user performed the action.
IMPO RTAN T:

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.

74

FDK Programmer’s Guide

Executing Commands with API Functions

4

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
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 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.
FDK Programmer’s Guide

75

4

Executing Commands with API Functions

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 Structured 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 FrameMaker commands
that manipulate elements.
The syntax for these functions is:
VoidT
VoidT
VoidT
VoidT
VoidT
VoidT
VoidT

76

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);

FDK Programmer’s Guide

Executing Commands with API Functions

This argument

Means

docId

ID of the document containing selected text and/or structure elements

edefId

ID of element definition for the new element

4

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 114. For more information
on setting the element selection programmatically, see “Getting and setting the structural
element selection” on page 120

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().
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.

FDK Programmer’s Guide

77

4

Executing Commands with API Functions

Flag

Meaning

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().
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 SGML 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.

GenerateDoc

Instructs the structure generator to generate structure, using the
strings listed above.

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:

78

FDK Programmer’s Guide

Executing Commands with API Functions

4

. . .
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", "GenerateDoc");
. . .

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 ‘‘Calling Clients Shipped With FrameMaker’’ on page 699 of the FDK
Programmer’s Reference.

FDK Programmer’s Guide

79

4

80

Executing Commands with API Functions

FDK Programmer’s Guide

5

Getting and Setting Properties

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.
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, see Part II, Frame Product Architecture.

FDK Programmer’s Guide

81

5

Getting and Setting Properties

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 631 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.”
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);

82

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.

FDK Programmer’s Guide

Getting and Setting Properties

5

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 13.2 on page 276.
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);
}
. . .

FDK Programmer’s Guide

83

5

Getting and Setting Properties

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.

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.
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

84

FDK Programmer’s Guide

Getting and Setting Properties

5

(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);
. . .
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

FDK Programmer’s Guide

85

5

Getting and Setting Properties

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 14, “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.
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 304.

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().

86

FDK Programmer’s Guide

Getting and Setting Properties

5

For background information on selection in Frame documents, see “How the API represents
the selection in a document” on page 285. For information on getting selected text, see
“Getting and setting the insertion point or text selection” on page 114.
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 114.
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 120.

FDK Programmer’s Guide

87

5

Getting and Setting Properties

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_CombinedFontDefn

●

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.
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:

88

FDK Programmer’s Guide

Getting and Setting Properties

5

. . .
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 assigns 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().
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 185 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.

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

FDK Programmer’s Guide

89

5

Getting and Setting Properties

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” of 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”

90

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()

F_StringsT

F_ApiGetStrings()
F_ApiSetStrings()

F_TabsT

F_ApiGetTabs()
F_ApiSetTabs()

F_TextLocT

F_ApiGetTextLoc()
F_ApiSetTextLoc()

F_TextRangeT

F_ApiGetTextRange()
F_ApiSetTextRange()

FDK Programmer’s Guide

Getting and Setting Properties

5

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);
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

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
‘‘Object Reference’’ on page 495 of 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");

FDK Programmer’s Guide

91

5

Getting and Setting Properties

/* 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

To get and set property lists, you need to understand how the API represents them. For more
information, see “Property lists” on page 272.
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.

92

FDK Programmer’s Guide

Getting and Setting Properties

5

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 different
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.
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

FDK Programmer’s Guide

93

5

Getting and Setting Properties

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 interface. 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 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.

94

FDK Programmer’s Guide

Getting and Setting Properties

5

. . .
#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.

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.

FDK Programmer’s Guide

95

5

Getting and Setting Properties

Getting the user home, $FMHOME, and current directories
Some platforms (such as UNIX) support the concepts of user home, $FMHOME, and current
directories. The following code displays the names of these directories for the current session:
. . .
#include "futils.h"
StringT homeDir, fmhomeDir, currentDir;
UCharT msg[512];
/* Get directory names. */
homeDir = F_ApiGetString(0, FV_SessionId, FP_UserHomeDir);
fmhomeDir = F_ApiGetString(0, FV_SessionId, FP_FM_HomeDir);
currentDir = F_ApiGetString(0, FV_SessionId, FP_FM_CurrentDir);
F_Sprintf(msg, "Home dir: %s. FMHOME: %s. Current dir: %s",
homeDir, fmhomeDir, currentDir);
/* Display the directory names in an alert box. */
F_ApiAlert(msg, FF_ALERT_CONTINUE_NOTE);
/* Free the strings. */
F_Free(homeDir);
F_Free(fmhomeDir);
F_Free(currentDir);
. . .

Disabling redisplaying to avoid screen flicker
If you change numerous properties at once, it may cause screen flicker, an effect that occurs
when the FrameMaker product executes a long series of changes that aren’t user-initiated. By
default, FrameMaker reformats the document 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);

For example, to change a number of properties at once, use code similar to the following:

96

FDK Programmer’s Guide

Getting and Setting Properties

5

. . .
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.

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.

FDK Programmer’s Guide

97

5

Getting and Setting Properties

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");
. . .

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 overwrites 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.
IMPO RTAN T:

98

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 fcodes to an invisible document.

FDK Programmer’s Guide

Getting and Setting Properties

5

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);
. . .

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:

FDK Programmer’s Guide

99

5

Getting and Setting Properties

. . .
#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 295 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.

Moving graphics forward or back in the draw order
FrameMaker maintains 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-tofront 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:

100

FDK Programmer’s Guide

Getting and Setting Properties

5

. . .
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);
}
. . .

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 289.
For an example of how to move objects from a frame to a page frame, see ‘‘F_ApiSetId()’’ on
page 285 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 146.
To remove an object from a group, set the object’s FP_GroupParent property to 0.

FDK Programmer’s Guide

101

5

Getting and Setting Properties

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 592 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 92. 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.

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 - then get selection. */
bodyFmtId = F_ApiGetNamedObject(docId, FO_PgfFmt, "Body");
if (!bodyFmtId) return;
tr = F_ApiGetTextRange(FV_SessionId,docId, FP_TextSelection);
if(tr.beg.objId == 0) return;
/*
* Get properties from the Body Paragraph Catalog format.
* Then apply Body properties to paragraph containing insertion
* point (or the beginning of the text selection).

102

FDK Programmer’s Guide

Getting and Setting Properties

5

*/
props = F_ApiGetProps(docId, bodyFmtId);
if(props.len == 0) return;
F_ApiSetProps(docId, tr.beg.objId, &props);
. . .

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);
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.

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

103

5

Getting and Setting Properties

This argument

Means

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-toright 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 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);

104

FDK Programmer’s Guide

Getting and Setting Properties

5

F_ApiDeallocateTabs(&tabs);
. . .

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);
. . .

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 FrameMaker 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 direct children of 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,

FDK Programmer’s Guide

105

5

Getting and Setting Properties

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:
●

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 582 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.
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;

106

FDK Programmer’s Guide

Getting and Setting Properties

5

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.
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.

FDK Programmer’s Guide

107

5

Getting and Setting Properties

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 152.

Setting element definition properties
Element definitions have the following properties that are only indirectly settable:
●

FP_TextFmtRules

●

FP_ObjectFmtRules

●

FP_PrefixRules

●

FP_SuffixRules

●

FP_FirstPgfRules

●

FP_LastPgfRules

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:

108

●

FP_MatchingTextClauses

●

FP_MatchingObjectClauses

●

FP_MatchingPrefixClauses

●

FP_MatchingSuffixClauses

FDK Programmer’s Guide

Getting and Setting Properties

●

FP_MatchingFirstPgfClauses

●

FP_MatchingLastPgfClauses

5

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, 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.

FDK Programmer’s Guide

109

5

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 FrameMaker 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.

110

FDK Programmer’s Guide

6

Manipulating Text

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 311.

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 82.
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.

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 164 of the FDK Programmer’s
Reference.

FDK Programmer’s Guide

111

6

Manipulating Text

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;

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 312.
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

112

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 crossreference.

FV_FO_FOOTNOTE

All the text items from the beginning to the end of the
footnote.

FDK Programmer’s Guide

Manipulating Text

Element’s FP_ElementType
value

6

Information returned by F_ApiGetText()

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.

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);
. . .

FDK Programmer’s Guide

113

6

Manipulating Text

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.
Subcolum

Text frame

FIGURE 6.1

Page with text frame containing two subcolumns

The fields of the F_TextRangeT structure specified by the document’s
FP_TextSelection property have the following values:

114

FDK Programmer’s Guide

Manipulating Text

Field

Value

beg.objId

ID of the first paragraph

beg.offset

0

end.objId

ID of the first paragraph

end.offset

5

6

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

IMPO RTAN T:

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:
Field

Value

beg.objId

0

beg.offset

0

end.objId

0

end.offset

0

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 285.
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.

FDK Programmer’s Guide

115

6

Manipulating Text

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.
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:

116

FDK Programmer’s Guide

Manipulating Text

6

. . .
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);
. . .

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

117

6

Manipulating Text

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 164 of
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);
. . .

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 87.
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 201 of the FDK Programmer’s
Reference.

118

FDK Programmer’s Guide

Manipulating Text

6

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.
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 {
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);

FDK Programmer’s Guide

119

6

Manipulating Text

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.

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 286. For
examples of how to get and set element selections, see “F_ApiGetElementRange()” on
page 113 and ‘‘F_ApiSetElementRange()’’ on page 282 of the FDK Programmer’s Reference.

120

FDK Programmer’s Guide

Manipulating Text

6

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.

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 316. 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

121

6

Manipulating 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);
. . .

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);

122

FDK Programmer’s Guide

Manipulating Text

6

/* 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 154.

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 102.

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.

FDK Programmer’s Guide

123

6

Manipulating Text

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 312.
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

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:

124

FDK Programmer’s Guide

Manipulating Text

6

. . .
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.
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.4
Linearized                      : No
Subject                         : FDK Documentation
Modify Date                     : 2002:09:16 16:13:51+02:00
Keywords                        : FDK, API, C, Plugins, Clients
Create Date                     : 2002:09:16 14:47:57Z
Page Count                      : 482
Creation Date                   : 2002:09:16 14:47:57Z
Mod Date                        : 2002:09:16 16:13:51+02:00
Producer                        : Acrobat Distiller 5.0.5 (Windows)
Author                          : Adobe Solutions Network
Metadata Date                   : 2002:09:16 16:13:51+02:00
Creator                         : Adobe Solutions Network
Title                           : FDK Programmer’s Guide
Description                     : FDK Documentation
Page Mode                       : UseOutlines
EXIF Metadata provided by EXIF.tools

Navigation menu