Adobe InDesign CS4 Solutions In Design

User Manual: adobe InDesign - CS4 - Solutions Free User Guide for Adobe InDesign Software, Manual

Open the PDF directly: View PDF PDF.
Page Count: 307 [warning: Documents this large are best viewed by clicking the View PDF Link!]

ADOBE® INDESIGN® CS4
ADOBE INDESIGN CS4 SOLUTIONS
© 2008 Adobe Systems Incorporated. All rights reserved.
Adobe InDesign CS4 Solutions
If this guide is distributed with software that includes an end user agreement, this guide, 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. Except as permitted by any such license, no part of this guide 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 note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license
agreement.
The content of this guide 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 the informational content
contained in this guide.
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, Bridge, Creative Suite, Flex, Flex Builder, Illustrator, InCopy, InDesign, Photoshop, and Reader are either registered trademarks or
trademarks of Adobe Systems Incorporated in the United States and/or other countries. Microsoft and Windows are either registered trademarks or trademarks of
Microsoft Corporation in the United States and/or other countries. Apple and Mac OS are trademarks of Apple Computer, Incorporated, registered in the United
States and other countries. All other trademarks are the property of their respective owners.
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 herein.
Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S.
Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as
amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as
amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding
sentence shall be incorporated by reference.
3
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Documents. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Spreads and Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Master Spreads and Master Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Page Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Guides and Grids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Layout Windows and Layout Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Story Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Text Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Text Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Rendered Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Text Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Text Hyphenation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Find/Change Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100
Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .105
Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .107
Tables and Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109
Text in Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .111
Table and Cell Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113
Contents
Contents
4Adobe InDesign CS4 Solutions
Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .119
Paths. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .119
Graphic Page Items. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .122
Colors and Swatches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .130
Graphic Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .133
Drawing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .141
Frequently Asked Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .143
Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .153
Working with Selection Suites Provided by the API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .154
Creating Selection Suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .160
User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169
Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171
Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .174
Progress Bars. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175
Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .176
Palettes and Panels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .181
Static Text Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .193
Check Boxes and Radio Buttons. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .196
Button Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .198
Edit Boxes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .202
Image Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .206
Drop-Down Lists and Combo Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .208
Splitter Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .211
Scroll Bars. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .212
Sliders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .213
Tree-view Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .216
The Quick Apply Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .225
Adobe InDesign CS4 Solutions 5
Contents
XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
The XML User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .227
XML Import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .229
XML Export. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .236
Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .238
Elements and Content. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .247
XSLT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .259
Versioning Persistent Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261
Working with Data Conversion Strategies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .262
Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Finding commands provided by the API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .269
Spying on command processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .270
Processing a command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .271
Scheduling a command. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .272
Processing a command sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .273
Processing an abortable command sequence. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .274
Fixing assert “DataBase change outside of Begin/End Transaction!” . . . . . . . . . . . . . . . . . . .275
Notification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Finding responder events and their associated ServiceID . . . . . . . . . . . . . . . . . . . . . . . . . .277
Spying on observer notification broadcasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .280
Accessing lazy notification data objects used by the application. . . . . . . . . . . . . . . . . . . . . .280
Using lazy notification data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .281
Snippets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Working with snippet export . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .285
Working with snippet import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .289
Working with snippets and libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .291
Contents
6Adobe InDesign CS4 Solutions
InCopy: Assignments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Creating an assignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .295
Adding content to an assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .296
Examining the content of an assignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .296
Deleting an assignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .297
Flash/FlexUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .299
Flash/Flex from a C++ plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .300
Flash/Flex from ScriptUI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .304
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .307
Introduction 7
Introduction
Introduction
This document offers step-by-step instructions to developers embarking on Adobe® InDesig
development tasks. It includes references to other SDK documentation, tools, and samples, and
it helps developers determine which InDesign API to use for different tasks.
Before the information in this document is of much value, you will need to become familiar
with the architecture. If you are new to InDesign development, we recommend approaching
the documentation as follows:
1. Getting Started With the Adobe InDesign CS4 Products SDK provides an overview of the
SDK, as well as a tutorial that takes you through the tools and steps to build your first plug-
in.
2. Learning Adobe InDesign CS4 Plug-in Development introduces the most common program-
ming constructs for InDesign development. This includes an introduction to the InDesign
object model and basic information on user-interface options, scripting, localization, and
best practices for structuring your plug-in.
3. The SDK itself includes several sample projects. All samples are described in the “Samples
section of the API reference. This is a great opportunity to find sample code that does some-
thing similar to what you want to do, and study it.
4. This manual provides step-by-step instructions (or “recipes”) for accomplishing various
tasks. If your particular task is covered by this guide, reading it can save you a lot of time.
5. Adobe InDesign CS4 Products Programming Guide provides the most complete, in-depth
information on plug-in development for InDesign CS4 products.
Introduction
8
Layout 9
Layout
Getting Started
Layout
Getting Started
This chapter presents layout-related use cases. To solve a layout-related programming problem,
like creating a spread or finding the frames in a spread, look for a use case that matches your
needs.
To learn about how layout works and is organized under the hood, do the following:
zRun through the activities in “Exploring Layout with SnippetRunner” on page 9, to learn
how to explore the layout-related objects in a document and familiarize yourself with lay-
out-related sample code.
zRead the “Layout Fundamentals” chapter in Adobe InDesign CS4 Programming Guide.
Exploring Layout with SnippetRunner
SnippetRunner is a plug-in that lets you run code snippets provided in the SDK. Several code
snippets are provided that let you explore the layout-related objects in a document.
Solution
1. Run Adobe® InDesign® with the SnippetRunner plug-in present. For instructions on using
the plug-in, see the API documentation page for SnippetRunner.
2. Run the CreateDocument code snippet.
3. Run the InspectLayoutModel code snippet to create a textual report about the objects in the
document’s layout hierarchy.
4. Run the CreateFrame code snippet.
5. Deselect the new frame and run the InspectLayoutModel code snippet, to see how the doc-
uments layout hierarchy has changed. A new kSplineItemBoss is created.
NOTE:If an object is selected, InspectLayoutModel reports the hierarchy of only the selected
object. If nothing is selected, it reports the hierarchy of the entire document.
6. Run the PlaceFile code snippet, and place an image file.
7. Make sure the placed frame is selected, and run the InspectLayoutModel code snippet to
report the objects in the hierarchy of the graphic frame.
Layout
Getting Started
10
8. Create other objects in a document or open documents containing layouts you want to
examine, and use InspectLayoutModel to examine the boss objects representing the layout
hierarchy.
9. Browse the sample code in the snippets you have been running.
Sample Code
zSnpCreateDocument
zSnpInspectLayoutModel
zSnpCreateFrame
zSDKLayoutHelper
Related APIs
zIDocument
zIDocumentLayer
zIHierarchy
zIMasterSpreadList
zISpread
zISpreadLayer
zISpreadList
Finding Layout-related Resources in the SDK
You can locate assets in the SDK that will help you program with the layout subsystem.
Solution
1. See Adobe InDesign CS4 Programming Guide, in the docs/guides folder. The “Layout Funda-
mentals chapter covers the layout subsystem.
2. See the API documentation in docs/references/index.chm or in HTML format. There are
documentation pages for boss classes and interfaces. Sample code related to layout is on the
Layout Samples page.
Layout 11
Layout
Documents
Documents
Acquiring a Reference to a Document
Solution
A document (kDocBoss) is characterized by the IDocument interface. A UIDRef that can
instantiate an IDocument interface is a document.
To iterate through documents, use IDocumentList to list the documents the application has
open. See “Iterating through Documents” on page 14.
If you have an IDataBase pointer, call IDataBase::GetRootUID. The document associated with
a database (if any) can be discovered using code like the following:
InterfacePtr<IDocument> document(db, db->GetRootUID(), UseDefaultIID());
if (document != nil) // use the document interface
If you have a UIDRef, follow these steps:
1. Call UIDRef::GetDataBase to discover the IDataBase pointer.
2. Use the pointer to acquire the document as described above.
If you have an interface pointer for any interface on a UID-based object (for example, an IHier-
archy interface), follow these steps:
1. Call the PersistUtils function ::GetDataBase to discover the IDataBase pointer.
2. Use the pointer to acquire the document as described above.
If you have an IActiveContext interface, call IActiveContext::GetContextDocument. The docu-
ment associated with this context (if any) can be found using code like the following:
IDocument* document = activeContext->GetContextDocument();
if (document != nil) // use the document interface
If you have a layout view, call ILayoutControlData::GetDocument. For details, in the “Layout
Fundamentals” chapter of Adobe InDesign CS4 Programming Guide, see “The Layout Window
and View” section. This call often is used by trackers (ITracker).
To work with the document the user is editing, call ILayoutUIUtils::GetFrontDocument.
Related API
IDocument
Layout
Documents
12
Creating a Document
Creating a Document with a Setup of your Own Choice
You can create a document and specify the number of pages, page size, and so on that the new
document should have.
Solution
1. To create the command, call IDocumentCommands::CreateNewCommand.
2. Populate the command's INewDocCmdData data interface to describe the desired set-up.
3. Process the command.
Sample Code
zSDKLayoutHelper::CreateDocument
zSnpCreateDocument
Creating a Document using the Default Document Setup
Solution
Call IDocumentCommands::New with the syleToUse parameter set to nil.
Related APIs
zIDocument
zIDocumentCommands
zIPageSetupPrefs
Creating a Document from a Document Preset
Solution
1. Using IDocStyleListMgr, find the name of the preset style (kDocStyleBoss) on which you
want to base your document.
2. Call IDocumentCommands::New, passing the name of the preset in the syleToUse parame-
ter.
Related APIs
zIDocument
zIDocumentCommands
Layout 13
Layout
Documents
Opening an Existing Document
Solution
Use IDocumentCommands::Open.
Sample Code
SDKLayoutHelper::OpenDocument
Related APIs
zIDocumentCommands
zIDocument
Saving a Document
Saving a Document to a File
Solution
If you already know where the file to save into is located or you want full control over how the
user is prompted for the file location, call IDocumentCommands::SaveAs.
If you want the user to be asked to identify the file to save to using the applications save file dia-
log, call IDocFileHandler::SaveAs.
Sample Code
SDKLayoutHelper::SaveDocumentAs
Related API
IDocumentCommands
Saving a Document
You can save a document that was saved to a file at least once before (IDocument::IsSaved indi-
cates this).
Solution
Call one of the following
zIDocumentCommands::Save
zIDocFileHandler::Save
Related APIs
zIDocument
zIDocumentCommands
zIDocFileHandler
Layout
Documents
14
Closing a Document
Solution
To close any layout windows that are open, then schedule a command to close the document,
use IDocFileHandler::Close.
To process a command to close the document immediately, use IDocumentCommands::Close.
Sample Code
SDKLayoutHelper::CloseDocument
Related API
IDocument
Iterating through Documents
You can examine all open documents.
Solution
1. Use the session returned from GetExecutionContextSession() to call ISession::QueryAppli-
cation.
2. Call IApplication::QueryDocumentList.
3. Examine the documents using IDocumentList
Sample Code
InterfacePtr<IApplication> application(GetExecutionContextSession()-
>QueryApplication());
InterfacePtr<IDocumentList> documentList(application->QueryDocumentList());
for (int32 i = 0; i < documentList->GetDocCount(); i++) {
IDocument* document = documentList->GetNthDoc(i);
PMString name;
document->GetName(name);
}
Related API
IDocument
Layout 15
Layout
Documents
Finding the Default InDesign Document Setup
You can find the properties displayed in the File > Document Setup and File > New Document
dialogs.
Solution
To get the defaults inherited by new documents, use IPageSetupPrefs on kWorkspaceBoss.
To get the settings for a document, use IPageSetupPrefs on kDocWorkspaceBoss.
Sample Code
SnpModifyLayoutGrid
Related API
IPageSetupPrefs
Changing the Default InDesign Document Setup
Solution
Use kSetPageSetupPrefsCmdBoss.
Related Documentation
zSee “Finding the Default InDesign Document Setup” on page 15.
Related API
IPageSetupPrefs
Getting Notified when Documents are Created, Opened, Saved, or Closed
Solution
Implement a document signal responder service (IResponder).
Sample Code
DocWatch
Related APIs
zDocWchResponder::Respond catalogs the ServiceIDs.
zIK2ServiceProvider
zIResponder
Layout
Spreads and Pages
16
Spreads and Pages
Acquiring a Reference to a Spread
Solution
A spread (kSpreadBoss) is characterized by the ISpread interface. A UIDRef that can instanti-
ate an ISpread interface is a spread.
To iterate through the spreads (kSpreadBoss) in a document (see “A c q u i r i n g a R e f e r e n c e t o a
Document” on page 11), use ISpreadList.
If you have an IHierarchy interface on a page item, use the following:
zIHierarchy::GetSpreadUID.
zIPasteboardUtils::QuerySpread. This utility gives you the ISpread interface of the spread
that owns the object whose IHierarchy interface you already have.
NOTE:If you have another page item interface like IGeometry or ITransform, query that
interface for IHierarchy, then call the method above to get a reference to the spread.
If you have a layout view and want to find the spread being edited, use ILayoutControl-
Data::GetSpread.
If you have a document and want to find the spread being edited, use
IID_ICURRENTSPREAD on kDocBoss. This is an IPersistUIDData interface that stores the
current spread for a document.
To hit test for a spread, use IPasteboardUtils.
Sample Code
zBscDNDCustomFlavorHelper::ProcessDragDropCommand
zCHMLFiltHelper::collectGraphicFrames
zSnapTracker::BeginTracking
zSnpInspectLayoutModel
Related APIs
zISpread
zkSpreadBoss
Layout 17
Layout
Spreads and Pages
Creating a Spread
Solution
Use kNewSpreadCmdBoss.
Related APIs
zISpread
zkSpreadBoss
Deleting a Spread
Solution
Use kDeleteSpreadCmdBoss.
Related APIs
zISpread
zkSpreadBoss
Iterating through Spreads
You can examine all spreads in a document.
Solution
Use ISpreadList.
Sample Code
zCHMLFiltHelper::collectGraphicFrames
zSnpInspectLayoutModel
Related APIs
zISpread
zkSpreadBoss
Layout
Spreads and Pages
18
Rearranging the Order of Spreads
You can rearrange the order of spreads in a document; for example, move the spread contain-
ing pages 2 and 3 so these pages precede the spread containing pages 6 and 7.
Solution
Use kMoveSpreadCmdBoss.
Related APIs
zISpread
zISpreadList
Copying a Spread
You can duplicate a spread and the page items it contains.
Solution
To append the duplicated spread to the spread list (ISpreadList) in the target document, pro-
cess kCreateSpreadFromSpreadCmdBoss.
To control where in the spread list (ISpreadList) the spread is positioned, follow these steps:
1. Process kNewSpreadCmdBoss to create a new spread at a position of your choice in the tar-
get document’s spread list.
2. Process kDuplicateSpreadCmdBoss to copy the source spread.
Iterating through the Content of a Spread
Solution
Use IHierarchy on kSpreadBoss.
Related Documentation
z“Iterating through Page Content” on page 21.
z“Iterating through Layer Content” on page 27.
Sample Code
zSnpInspectLayoutModel
zIn the “Layout Fundamentals” chapter of Adobe InDesign CS4 Programming Guide, see two
examples: “Code that Iterates through Spreads and Visits their Children via IHierarchy” and
Code that Iterates through Spreads and Filters Items by Page via ISpread”.
Layout 19
Layout
Spreads and Pages
Acquiring a Reference to a Page
Solution
A page (kPageBoss) is characterized by the IMasterPage interface. A UIDRef that can instanti-
ate an IMasterPage interface is a page.
If you have a document (see Acquiring a Reference to a Document” on page 11) and want to
iterate through its pages, use IPageList. See Acquiring a Reference to a Page” on page 19.
If you have a spread (see Acquiring a Reference to a Spread” on page 16) and want to iterate
through its pages, use the following:
zISpread::GetNumPages and ISpread::GetNthPageUID provide easy access to the pages.
zISpread::QueryPagesLayer provides access to the spread layer that stores the pages on its
IHierarchy. The child boss objects of this spread layer are the pages owned by the spread.
If you have a page item and want to know the page, if any, on which it lies or is drawn, use the
following:
zILayoutUtils::GetOwnerPageUID
zILayoutUtils::GetDrawingPageUID
If you have a layout view(kLayoutWidgetBoss), use ILayoutControlData::GetPage, to get the
page being viewed by the user in layout view.
Sample Code
zCHMLFiltImportProvider::LoadImage
zSnpCreateInddPreview::CreateFirstPagePreview
Related API
kPageBoss
Creating a Page
Solution
Use kNewPageCmdBoss.
Related API
kPageBoss
Layout
Spreads and Pages
20
Deleting a Page
You can delete a page and the page items on it.
Solution
Use kDeletePageCmdBoss.
Related API
kPageBoss
Iterating through Pages
You can examine the pages in a document or the pages in a spread.
Solution
To iterate through all pages in a document, use IPageList.
NOTE:IPageList does not list master pages (the pages owned by master spreads). It lists only
pages owned by spreads (kSpreadBoss).
To iterate through all pages in a spread, use ISpread.
Sample Code
CHMLFiltImportProvider::LoadImage
Related APIs
zIPageList
zISpread
zkPageBoss
Rearranging Pages
You can rearrange the order of pages in a document.
Solution
Use kMovePageCmdBoss.
Related APIs
zIPageList
zkPageBoss
Layout 21
Layout
Spreads and Pages
Copying a Page
You can duplicate a page together with the page items on it.
Solution
To append the duplicated page to the target document, use kCreatePageFromPageCmdBoss.
To control the spread in which the duplicate is made, do one of the following:
zCreate a new spread for the page using kNewSpreadCmdBoss.
zProcess kDuplicatePageCmdBoss.
Related API
kPageBoss
Iterating through Page Content
You can iterate through page items on a page.
Solution
Use ISpread::GetItemsOnPage.
Sample Code
zCHMLFiltImportProvider::LoadImage
zIn the “Layout Fundamentalschapter of Adobe InDesign CS4 Programming Guide, see the
example entitled “Code that Iterates through Spreads and Filters Items by Page via ISpread.
Related APIs
zISpread
zkPageBoss
Finding Page Size
Solution
If you have a reference to a page (kPageBoss), use IGeometry::GetStrokeBoundingBox to get
the size of each page.
If you have a reference to the documents workspace (kDocWorkspaceBoss), use
IPageSetupPrefs to get the default page size inherited by new pages.
NOTE:The size of each page (kPageBoss) in a document is the same and always agrees with the
default page size stored in IPageSetupPrefs.
Sample Code
SnpModifyLayoutGrid
Layout
Spreads and Pages
22
Related API
kPageBoss
Changing Page Size
You can change the size of all pages in a document.
Solution
Use kSetPageSetupPrefsCmdBoss to change the default page size and the size of all pages.
Related API
kPageBoss
Finding Page Margins
Solution
Use IMargins. Each page (kPageBoss) has its own margins.
Sample Code
zCHMLFiltHelper::addGraphicFrameDescription
zSDKLayoutHelper::PageToSpread
zSnpModifyLayoutGrid
Related API
kPageBoss
Changing Page Margins
Solution
Use kSetPageMarginsCmdBoss.
Sample Code
SnpModifyLayoutGrid
Related API
kPageBoss
Layout 23
Layout
Spreads and Pages
Finding Page Column Guides
Solution
Use IColumns. Each page (kPageBoss) has its own column guides.
Sample Code
zSnpModifyLayoutGrid
Related API
kPageBoss
Changing Page Column Guides
Solution
Use the following:
zkSetPageColumnsCmdBoss
zkSetColumnGutterCmdBoss
Sample Code
SnpModifyLayoutGrid
Related API
kPageBoss
Getting Notified of Spread and Page Operations
Solution
Implement a document observer interested in IID_ISPREADLIST.
NOTE:This approach works for commands that create, delete, arrange, and copy spreads and
pages but not for all spread and page manipulations. For details of the subject you need
to observe, see the API documentation for the command used to perform the operation
in which you are interested.
Related APIs
zIDocument
zIObserver
zISubject
Layout
Layers
24
Layers
Acquiring a Reference to a Layer
A layer comprises a document layer with two corresponding spread layers in each spread in the
document. Spread layers own page items. If you want a boss object to act as a parent for a new
page item, you will need a reference to a spread layer.
Acquiring a Reference to a Document Layer
Solution
A document layer (kDocumentLayerBoss) is characterized by the IDocumentLayer interface.
A UIDRef that can instantiate an IDocumentLayer interface is a document layer.
If you have a document (see Acquiring a Reference to a Document” on page 11) and want to
examine all the document layers, use ILayerList.
If you have a document and want to find the document layer targeted for edit operations, use
ILayerUtils::QueryDocumentActiveLayer.
If you have a spread layer and want to find its associated document layer, use ISpread-
Layer::QueryDocLayer.
If you have a reference to a page item and want to find its associated document layer, Call
ILayerUtils::GetLayerUID to get the spread layer that owns the page item, then call ISpread-
Layer::QueryDocLayer.
If you have a layout view and want to find the document layer targeted for edit, use ILayout-
ControlData::QueryActiveDocLayer or ILayoutControlData::GetActiveDocLayerUID give the
active document layer.
If you have an IActiveContext interface, use ILayerUIUtils::QueryContextActiveLayer.
Sample Code
zSDKLayoutHelper
zSnpInspectLayoutModel
Related API
kDocumentLayer
Layout 25
Layout
Layers
Acquiring a Reference to a Spread Layer
Solution
A spread layer (kSpreadLayerBoss) is characterized by the ISpreadLayer interface. A UIDRef
that can instantiate an ISpreadLayer interface is a spread layer.
If you have a spread (see Acquiring a Reference to a Spread” on page 16) and a document layer
(see Acquiring a Reference to a Document Layer” on page 24), use ISpread::QueryLayer to get
the content or guide spread layer (kSpreadLayerBoss) associated with the document layer.
If you have a page item and want to know the spread layer that owns it, use IHierarchy::Get-
LayerUID.
NOTE:Some hierarchies, like those for an inline frame (kInlineBoss), return kInvalidUID. If
you are working with inline frames, use IPageItemUtils::QueryInlineParentPageItem to
find the page item in the layout hierarchy first, then find the spread layer.
If you have a layout view and want to find the spread layer targeted for edit operations, use
ILayoutControlData::QueryActiveLayer or ILayoutControlData::GetActiveLayerUID to get
the active spread layer. This is useful if you want to parent page items created by your plug-in
on the same layer the user is editing.
Sample Code
zSDKLayoutHelper::GetActiveSpreadLayerRef
zSnpInspectLayoutModel
Related API
kSpreadLayer
Creating a Layer
Solution
Use kNewLayerCmdBoss.
Sample Code
SnpProcessDocumentLayerCmds::CreateNewLayer
Related APIs
zkDocumentLayer
zkSpreadLayer
Layout
Layers
26
Deleting a Layer
You can delete a layer and its associated content.
Solution
Use kDeleteLayerCmdBoss.
Related APIs
zkDocumentLayer
zkSpreadLayer
Iterating through Layers
You can examine the layers in a document.
Solution
zUse ILayerList to get the document layers(kDocumentLayerBoss).
zUse ISpread::QueryLayer to get the spread layers associated with a document layer.
Sample Code
zSnpInspectLayoutModel
zIn the “Layout Fundamentalschapter of Adobe InDesign CS4 Programming Guide, see the
example entitled “Code that Iterates through Spreads in a Document, then Iterates through
Document Layers, to visit Items on the Spread Layer associated with each Document Layer.
Related APIs
zILayerList
zISpread
zkDocumentLayer
zkSpreadLayer
Rearranging the Order of Layers
Solution
Use kMoveLayerCmdBoss.
Related APIs
zkDocumentLayer
zkSpreadLayer
Layout 27
Layout
Layers
Copying a Layer
Solution
To append the duplicated layer to the end of the layer list (ILayerList) in the target document,
use kCreateLayerFromLayerCmdBoss.
To position the duplicate at a position of choice in the layer list (ILayerList), use the following:
1. kNewLayerCmdBoss creates a new layer.
2. kMoveLayerCmdBoss positions the new layer.
3. kDuplicateLayerCmdBoss copies the content.
Related APIs
zkDocumentLayer
zkSpreadLayer
Iterating through Layer Content
You can examine all page items assigned to a given layer on a spread.
Solution
1. Iterate through document layers using ILayerList.
2. Iterate through spreads using ISpreadList.
3. Iterate through the spread layers using ISpread::QueryLayer.
4. Examine the page items on the IHierarchy of each spread layer.
Sample Code
zSnpInspectLayoutModel
zIn the “Layout Fundamentalschapter of Adobe InDesign CS4 Programming Guide, see the
example “Code that Iterates through Spreads in a Document, then Iterates through Docu-
ment Layers, to visit Items on the Spread Layer associated with each Document Layer.
Locking and Unlocking a Layer
Solution
Use kLockLayerCmdBoss.
Related API
kDocumentLayer
Layout
Layers
28
Showing and Hiding a Layer
Solution
Use kShowLayerCmdBoss.
Related API
kDocumentLayer
Renaming a Layer
Solution
Use kChangeLayerNameCmdBoss.
Related API
kDocumentLayer
Changing Layer Color
Solution
Use kSetLayerColorCmdBoss.
Related API
kDocumentLayer
Merging Layers
You can merge two or more layers and the page items assigned to them into one layer.
Solution
Use kMergeLayersCmdBoss.
Related APIs
zkDocumentLayer
zkSpreadLayer
Layout 29
Layout
Master Spreads and Master Pages
Getting Notified of Layer Operations
Solution
Implement a document observer thats interested in IID_ILAYERLIST
Related APIs
zIDocument
zkDocumentLayer
zIObserver
zISubject
Master Spreads and Master Pages
Acquiring a Reference to a Master Spread
Solution
A master spread (kMasterpagesBoss) is characterized by the IMasterSpread interface. A
UIDRef that can instantiate an IMasterSpread interface is a master spread.
If you have a document (see Acquiring a Reference to a Document” on page 11) and want to
examine all the master spreads, use IMasterSpreadList.
If you have a page (see Acquiring a Reference to a Page” on page 19) and want to find its mas-
ter spread, use IMasterPage::GetMasterPageUID.
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Layout
Master Spreads and Master Pages
30
Creating a Master Spread
Solution
Use kNewMasterSpreadCmdBoss.
Related Documentation
zCopying a Master Spread on page 31
Related APIs
zIMasterPage
zkMasterPagesBoss
zIMasterSpread
zIMasterSpreadList
zkPageBoss
Deleting a Master Spread
Solution
Use kDeleteMasterSpreadCmdBoss.
Related APIs
zIMasterPage
zIMasterSpreadList
zkMasterPagesBoss
zIMasterSpread
zkPageBoss
Rearranging the Order of Master Spreads
Solution
The order of master spreads in the document is given by their index order in IMaster-
SpreadList. To re-arrange the order process, use kMoveMasterSpread.
Related APIs
zIMasterPage
zkMasterPagesBoss
zIMasterSpread
zkPageBoss
Layout 31
Layout
Master Spreads and Master Pages
Copying a Master Spread
You can duplicate a master spread and the page items it contains.
Solution
To append the duplicated master spread to the master spread list (IMasterSpreadList) in the
target document, use kCreateMasterFromMasterCmdBoss.
To control where in the master spread list (IMasterSpreadList) the master spread is positioned,
follow these steps:
1. Use kNewMasterSpreadCmdBoss to create a new master spread at a position of your choice
in the target documents master spread list.
2. Use kDuplicateSpreadCmdBoss to copy the source spread.
Saving a Spread as a Master Spread
You can create a master spread from a spread and the page items it contains.
Solution
To append the duplicated spread to the master spread list (IMasterSpreadList) in the target
document, use kCreateMasterFromSpreadCmdBoss.
To control where in the master spread list (IMasterSpreadList) the master spread is positioned,
follow these steps:
1. Use kNewMasterSpreadCmdBoss to create a new master spread at a position of your choice
in the target documents master spread list.
2. Use kDuplicateSpreadCmdBoss to copy the source spread.
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Layout
Master Spreads and Master Pages
32
Renaming a Master Spread
You can change the name or prefix of a master spread.
Solution
Use kRenameMasterSpreadCmdBoss.
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Acquiring a Pages Master Page
Solution
To get hold of a page if you do not have one, see Acquiring a Reference to a Page” on page 19.
Follow these steps:
1. Use IMasterPage::IsValid to determine whether the page has a master (if so, kTrue is
returned).
2. Use IMasterPage::GetMasterPageUID to return the UID of the associated master spread
(kMasterPagesBoss).
3. Use IMasterPage::GetMasterIndex to get the index of the master page in the master spread.
4. With the index, use ISpread::GetItemsOnPage to get the master spreads ISpread interface,
and call it to collect a list of all page items on the master page.
Sample Code
SnpInspectLayoutModel::TracePageNode
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Layout 33
Layout
Master Spreads and Master Pages
Distinguishing a Master Page from a Page
Solution
Both pages and master pages are represented by the same boss class kPageBoss (see “A c q u i r i n g
a Reference to a Page on page 19). To tell them apart, call ILayoutUtils::IsAMaster. A master
page is a page owned by a master spread (kMasterPagesBoss). This utility encapsulates the tests
that need to be made to determine this.
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Applying a Master Page to a Page
Solution
Use kApplyMasterSpreadCmdBoss.
Related APIs
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Showing and Hiding Master Page Items
Solution
Use kShowMasterItemsCmdBoss.
Related API
kSpreadBoss
Layout
Master Spreads and Master Pages
34
Overriding Master Page Items
Solution
To override master page items of your choice, use kOverrideMasterPageItemCmdBoss.
To override all the master page items associated with a range of spreads of pages, use IMaster-
SpreadUtils::CreateOverrideMasterPageItemsCmd.
Related APIs
zIMasterOverrideList
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Removing a Master Page Item Overrides
Solution
To remove the master page item overrides of your choice, use kRemoveMasterPageOverrideC-
mdBoss.
To remove master page item overrides of objects that are selected, use IMasterPageSuite.
Related APIs
zIMasterOverrideList
zIMasterPage
zIMasterSpread
zkMasterPagesBoss
zkPageBoss
Getting Notified of Master Spread and Master Page Operations
Solution
Implement a document observer interested in IID_ISPREADLIST.
NOTE:This approach works for commands that create, delete, arrange, and copy spreads and
pages but not for all spread and page manipulations. For details of the subject you need
to observe, see the API documentation for the command used to perform the operation
in which you are interested.
Layout 35
Layout
Page Items
Related APIs
zIDocument
zIObserver
zISubject
Page Items
Creating a Page Item
Creating an Empty Graphic Frame
Solution
1. Determine the UIDRef of the parent. The parent is the object that will own the frame. Nor-
mally, it is a spread layer (see Acquiring a Reference to a Spread Layer” on page 25).
2. Determine the bounding box for the frame to position and size it as desired. Normally,
frames are positioned relative to a page (see Acquiring a Reference to a Page on page 19).
3. Create the frame by calling the IPathUtils method that creates the path you want:
zUse IPathUtils::CreateRectangleSpline to create a rectangular path.
zUse IPathUtils::CreateOvalSpline to create an elliptical path.
zUse IPathUtils::CreateRegPolySpline to create a regular polygon path.
zUse IPathUtils::CreateSpline to get complete control of the path.
zUse attrType= INewPageItemCmdData::kGraphicFrameAttributes to create a placeholder
graphic frame (a frame with an X in it).
Example 1 shows code that, given a UIDRef to a document (kDocBoss), creates a frame at the
origin of the first page in the document. The parent for the frame is the spread layer associated
with the first content layer in the first spread in the document.
EXAMPLE 1 Create a 100*100 Point Square Graphic Frame at the Origin of the First Page
// 1. Determine the UIDRef of the parent.
InterfacePtr<ISpreadList> spreadList(docUIDRef, UseDefaultIID());
InterfacePtr<ISpread> spread(docUIDRef.GetDataBase(), spreadList-
>GetNthSpreadUID(0), UseDefaultIID());
InterfacePtr<ILayerList> layerList(docUIDRef, UseDefaultIID());
IDocumentLayer* documentLayer = layerList->GetLayer(1);
InterfacePtr<ISpreadLayer> spreadLayer(spread->QueryLayer(documentLayer));
UIDRef parentUIDRef = ::GetUIDRef(spreadLayer);
Layout
Page Items
36
if (spreadLayer->IsLocked() == kFalse) {
// 2. Determine the bounding box of the frame.
PMRect boundingBox(0, 0, 100, 100);
InterfacePtr<IGeometry> pageGeometry(spread->QueryNthPage(0));
::InnerToPasteboard(pageGeometry, &boundingBox);
// 3. Create the frame.
UIDRef frameUIDRef = Utils<IPathUtils>()->CreateRectangleSpline(parentUIDRef,
boundingBox,
INewPageItemCmdData::kGraphicFrameAttributes,
kTrue, Transform::PasteboardCoordinates() );
}
Sample Code
zSDKLayoutHelper::CreateRectangleFrame
zSnpCreateFrame
Related API
kSplineItemBoss
Creating a Path
Solution
1. See “Creating an Empty Graphic Frame” on page 35 for the basic approach. Frames and
paths both create spline item boss objects, kSplineItemBoss. The significant difference is
that a graphic frame is designated as being a container for a graphics page item.
2. On calling the IPathUtils create spline method that creates the path you want, use attrType=
INewPageItemCmdData::kGraphicAttribute to create a path.
Related Documentation
See “Creating an Empty Graphic Frame on page 35.
Sample Code
zSDKLayoutHelper::CreateRectangleGraphic
zSDKLayoutHelper::CreateSplineGraphic
zSnpCreateFrame
Related API
See Example 1 in Creating an Empty Graphic Frame” on page 35.
Layout 37
Layout
Page Items
Creating a Text Frame
Solution
Use kCreateMultiColumnItemCmdBoss.
Sample Code
zSDKLayoutHelper::CreatetextFrame
zSnpCreateFrame
Related APIs
zkMultiColumnItemBoss
zkSplineItemBoss
Deleting Page Items and their Contents
Solution
Use kDeleteCmdBoss.
Moving Page Items from one Spread to Another
Solution
Use kMoveToSpreadCmdBoss.
Moving Page Items from one Layer to Another
Solution
To move page items of your choice between layers, use kMoveToLayerCmdBoss.
To move page items that are currently selected between layers, use ILayerSuite
Copying Page Items within or across Documents
You can copy a page item and any nested page items it contains, either within the same docu-
ment or into another document.
Solution
Use kCopyCmdBoss.
Layout
Page Items
38
Copying Page Items to the Clipboard
Solution
To copy page items of your own choice to the clipboard, use kCopyCmdBoss.
To copy page items that are currently selected to the clipboard, use IScrapSuite::CanCopy and
IScrapSuite::Copy.
Pasting Page Items from the Clipboard
Solution
To paste page items from the clipboard into a document of your choice (the spread layer that
will be the parent of the pasted objects is specified by you), use kPasteCmdBoss.
To paste page items on the clipboard into a document being edited in layout view (the spread
and layer that will contain the pasted objects is designated by the view’s ILayoutControlData),
use IScrapSuite::CanPaste and IScrapSuite::Paste.
Removing Page Items from a Hierarchy
Solution
To remove one page item from its hierarchy, use IHierarchyUtils::RemoveFromHierarchy.
To more than one page item from its associated hierarchy, use kRemoveFromHierarchyCmd-
Boss.
Related API
IHierarchy
Adding Page Items to a Hierarchy
Solution
To add one page item into a hierarchy, use IHierarchyUtils::AddToHierarchy.
To add more than one page items to a hierarchy, use kAddToHierarchyCmdBoss.
Iterating through Frame Content
You can examine the content of a frame.
Solution
Query the frame for IFrameType to find the type of frame you have
Layout 39
Layout
Page Items
Finding the Frames in a Spread
Solution
1. Call ISpread::GetItemsOnPage to get the page items
2. Call IPageItemTypeUtils to find the type of each page item, or query the page items for an
IFrameType interface.
Sample Code
CHMLFiltHelper::collectGraphicFrames
Related APIs
zIHierarchy
zISpread
Searching for Page Items (Objects) with Certain Attributes
You may want to search/replace page items with certain graphic attributes. This section
describes how to set search/replace options and find page items (objects) according to object
style, frame type, and graphic attributes.
Solution
1. Set search mode to IFindChangeOptions::kObjectSearch, using kFindSearchModeCmd-
Boss.
2. In IFindChangeOptions, set object type to find, using kObjectSearchTypeCmdBoss. You
can choose from all frame types, graphic frames, and unassigned frames.
3. Set search scope using kScopeCmdBoss. The scope can be current document, all open doc-
uments, or within current selection. Do not forget to explicitly set the
IID_IFINDCHANGEMODEDATA interface on the command bosses to IFindChangeOp-
tions::kObjectSearch search mode.
4. Choose an object style to search, and prepare an attribute boss list to store graphic attributes
your found page item should have. Then, set the find object style and find attribute list
using kFindChangeFormatCmdBoss.
5. Perform a search by creating kFindChangeServiceBoss and calling IFindChangeSer-
vice::SearchObject().
Sample Code
SnpFindAndReplace::Do_FindObject
Layout
Page Items
40
Related APIs
zIFindChangeOptions on kWorkspaceBoss maintains all find/change options.
zIFindChangeService on kFindChangeServiceBoss provides find/change object services.
zCommands: kFindSearchModeCmdBoss, kScopeCmdBoss, kFindChangeFormatCmdBoss,
and kFindObjectBoss.
Replacing Page Items (Objects) with New Attributes
After finding an object, we may want to replace it with new attributes or replace and find the
next object. You also may want to find objects with specific attributes and replace them with
new attributes. This section describes how to set search/replace options and replace page items
(objects) according to both search/replace object style and graphic attributes.
Solution
Replacing shares most steps with searching. The following are the steps to set up options and
perform search and replace.
1. Set search mode to IFindChangeOptions::kObjectSearch, using kFindSearchModeCmd-
Boss.
2. In IFindChangeOptions, set object type to find, using kObjectSearchTypeCmdBoss. You
can choose from all frame types, graphic frames, and unassigned frames.
3. Set search scope using kScopeCmdBoss. The scope can be current document, all open doc-
uments, or within current selection. Do not forget to explicitly set the
IID_IFINDCHANGEMODEDATA interface on the command bosses to IFindChangeOp-
tions::kObjectSearch search mode.
4. Choose an object style to search and prepare an attribute boss list to store graphic attributes
your resulting page item should have. Then, set the find object style and find attribute list
using kFindChangeFormatCmdBoss.
5. Choose an object style to replace, and prepare an attribute boss list to store graphic
attributes your resulting page item should have. Then, set the change object style and
change attribute list using kFindChangeFormatCmdBoss. You may combine this step with
the previous step to the command is processed only once.
6. Perform a search by creating kFindChangeServiceBoss. Depending on what you want to do
with the found object(s), call IFindChangeService::ReplaceObject(), ReplaceAndSearchOb-
ject(), or ReplaceAllObject().
Sample Code
SnpFindAndReplace::Do_ReplaceObject
Layout 41
Layout
Guides and Grids
Related APIs
zIFindChangeOptions on kWorkspaceBoss maintains all find/change options.
zIFindChangeService on kFindChangeServiceBoss provides find/change object services.
zCommands: kFindSearchModeCmdBoss, kScopeCmdBoss, kFindChangeFormatCmdBoss,
kReplaceObjectCmdBoss, kReplaceFindObjectCmdBoss, and kReplaceAllObjectCmdBoss.
Guides and Grids
Acquiring a Reference to a Ruler Guide
Solution
A ruler (kGuideItemBoss) is characterized by the IGuideData interface. A UIDRef that can
instantiate an IGuideData interface is a ruler guide.
Follow these steps:
1. Acquire a reference to the spread containing the ruler guides (see Acquiring a Reference to
a Spread” on page 16). If you are starting from a page (kPageBoss), find the spread that
owns the page, then examine the spread layers that store guides as described below
2. To get the guide spread layers, call ISpread::QueryLayer with wantGuideLayer set to kTrue.
3. Examine the child objects on the spread layer’s IHierarchy. These are ruler guides
Sample Code
SnpInspectLayoutModel
Related API
kGuideItemBoss
Creating a Ruler Guide
Solution
Use kNewGuideCmdBoss.
Ruler guide properties are given by the IGuideData interface on kGuideItemBoss. When you
are creating a ruler guide, you specify the coordinates in their parent’s space, normally spread
coordinate space.
Layout
Guides and Grids
42
Sample Code
Example 2 demonstrates how to create a vertical guide item on the first page of the active
spread. For code simplicity, error checking is omitted.
EXAMPLE 2 Create a Vertical Ruler Guide
InterfacePtr<ILayoutControlData> layoutData(Utils<ILayoutUtils>()-
>QueryFrontLayoutData());
// Get the active document layer
InterfacePtr<IDocumentLayer> docLayer(layoutData->
QueryActiveDocLayer());
InterfacePtr<ISpread> spread(layoutData->GetSpread(), IID_ISPREAD);
IDataBase* db = ::GetDataBase(spread);
// Get the guide spread layer for the active spread.
InterfacePtr<ISpreadLayer> spreadLayer(spread->QueryLayer(docLayer, nil, kTrue));
// The parent for the new guide is the guide spread layer.
UID parent = ::GetUID(spreadLayer);
UIDRef parentUIDRef(db, parent);
// Get the first page UID. ownerUID is a page for short guides.
UID ownerUID = spread->GetNthPageUID(0);
// Note: The parent for the guide we are to create is the spread. Each
// page owns its guides. We need to convert the guide coordinates
// to its parent space - spread space.
// Get the bounding box of the page in spread space.
InterfacePtr<IGeometry> geometry(db, ownerUID, IID_IGEOMETRY);
PBPMRect bBox = geometry->
GetStrokeBoundingBox(::InnerToParentMatrix(geometry));
InterfacePtr<ICommand> newGuideCmd(CmdUtils::CreateCommand(kNewGuideCmdBoss));
InterfacePtr<INewGuideCmdData> newGuideCmdData(newGuideCmd, IID_INEWGUIDECMDDATA);
// The distance the guide is located at.
PMReal distance = bBox.Left() + bBox.GetHCenter();
// Get the default guide preference
InterfacePtr<IGuidePrefs>
iGuideDefault((IGuidePrefs*)::QueryPreferences(IID_IGUIDEPREFERENCES,
kGetFrontmostPrefs));
// Get the guide threshold and the color index
PMReal guideThreshold = iGuideDefault->GetGuidesThreshold();
int32 guideColorIndex = iGuideDefault->GetGuidesColorIndex();
newGuideCmdData->Set(parentUIDRef, kFalse, distance, ownerUID, kTrue,
guideThreshold, guideColorIndex);
Layout 43
Layout
Guides and Grids
if (CmdUtils::ProcessCommand(newGuideCmd) != kSuccess)
// Report process command failure.
Related APIs
zIGuideData
zIGuidePrefs
zkGuideItemBoss
zkNewGuideCmdBoss
Deleting a Ruler Guide
Solution
Use kDeleteCmdBoss.
Moving a Ruler Guide
Solution
To move the guide relative to its current position, use kMoveGuideRelativeCmdBoss.
To move the guide to an absolute position, use kMoveGuideAbsoluteCmdBoss.
Related API
kGuideItemBoss
Changing the Color, View Threshold, or Orientation of Ruler Guides
Solution
To change the color of a ruler guide, process the command created by calling IGui-
deUtils::MakeChangeColorGuideCmd.
To change the view threshold of a ruler guide, use kSetGuideViewThresholdCmdBoss.
To change the horizontal or vertical orientation of a ruler guide, use kSetGuideOrientationCm-
dBoss.
Related API
kGuideItemBoss
Layout
Guides and Grids
44
Showing and Hiding Guides
Solution
To show or hide all guides, use kSetGuidePrefsCmdBoss.
To show or hide ruler guides associated with a specific layer, use kShowGuideLayerCmdBoss.
Related API
kGuideItemBoss
Locking and Unlocking Guides
Solution
To lock or unlock all guides, use kSetGuidePrefsCmdBoss.
To lock or unlock ruler guides associated with a specific layer, use kLockGuideLayerCmdBoss.
Related API
kGuideItemBoss
Turning Snap to Guides On and Off
Solution
Use kSetSnapToPrefsCmdBoss.
Related API
kGuideItemBoss
Getting Notified of Guide and Grid Operations
Solution
1. Determine the command that is making the change in which you are interested.
2. See the API documentation page for that command.
3. Attach an observer to the subject changed by that command.
Related APIs
zIObserver
zISubject
Layout 45
Layout
Layout Windows and Layout Views
Layout Windows and Layout Views
Acquiring a Reference to a Layout Window
Solution
If you have a reference to a document (kDocBoss), use IPresentationList on kDocBoss to get
the windows (kLayoutPresentationBoss) open on a document (see Acquiring a Reference to a
Document” on page 11).
If you have an IActiveContext interface, use IActiveContext::GetContextView to get the layout
view associated with the context. From there, code like that in Example 3 gives the layout win-
dow:
EXAMPLE 3 Navigating from Layout View to Layout Window via IWidgetParent
// If you have a reference to a layout view (kLayoutWidgetBoss) the
// code below will find the associated layout window:
InterfacePtr<IWidgetParent> widgetParent(layoutView, UseDefaultIID());
InterfacePtr<IWindow> myWindow((IWindow*)widgetParent-
>QueryParentFor(IWindow::kDefaultIID));
To work with the window displaying the document the user is editing, use ILayoutU-
IUtils::QueryFrontView to get the layout view (kLayoutWidgetBoss) of the front document.
See Example 3 for the code that then gets the layout window.
To hit test for a layout window or iterate through windows on a document, use IDocumentU-
IUtils.
Related API
kLayoutPresentationBoss
Opening a Layout Window on a Document
Solution
Use kOpenLayoutCmdBoss.
Related Documentation
zOpening an Existing Document” on page 13
Sample Code
SDKLayoutHelper::OpenLayoutWindow
Layout
Layout Windows and Layout Views
46
Closing a Layout Window
Solution
Use kCloseLayoutCmdBoss.
Related Documentation
z“Closing a Document on page 14
Related API
kLayoutPresentationBoss
Iterating through Open Layout Windows
Solution
1. Use IDocumentList, to list the documents the application has open. See Iterating through
Documents” on page 14.
2. Use IPresentationList on each document, to list the windows open on it.
Related API
kLayoutPresentationBoss
Acquiring a Reference to a Layout View
Solution
If you have an IActiveContext interface, use IActiveContext::GetContextView.
If you have a layout window (kLayoutPresentationBoss) reference, use IPanelControl-
Data::FindWidget. Call with widgetId=kLayoutWidgetBoss) to get the window’s layout view.
To work with the layout view that is editing the document, follow these steps:
1. Use ILayoutUIUtils::QueryFrontView to get the layout view of the front document.
2. Use ILayoutUIUtils::QueryFrontLayoutData to get the ILayoutControlData interface for the
layout view of the front document.
Related API
kLayoutWidgetBoss
Layout 47
Layout
Layout Windows and Layout Views
Setting the Spread Targeted for Edit Operations
Solution
Use kSetSpreadCmdBoss.
Sample Code
zBscDNDCustomFlavorHelper::ProcessDragDropCommand
zSnapTracker::CreateAndProcessSetSpreadCmd
Related APIs
zILayoutControlData::GetSpread
zIID_ICURRENTSPREAD on kDocBoss
Setting the Layer Targeted for Edit Operations
Solution
Use kSetActiveLayerCmdBoss.
Sample Code
SnpProcessCmds
Related APIs
zILayoutControlData::QueryActiveDocLayer
zILayoutControlData::QueryActiveLayer returns the active spread layer (kSpreadLayer-
Boss).
zILayerUtils::QueryDocumentActiveLayer
Setting the Page viewed in a Layout Window
Solution
1. Get the ILayoutControlData interface of the layout view (kLayoutWidgetBoss).
2. Process kSetPageCmdBoss.
NOTE:The page being viewed is not stored anywhere. It is calculated each time
ILayoutControlData::GetPage is called, by finding the page whose center point is
closest to the center of the view.
Layout
Layout Windows and Layout Views
48
Related APIs
zILayoutControlData::GetPage
zILayoutUIUtils::GetVisiblePageUID
zkLayoutWidgetBoss
Fitting a Spread or Page in a Layout Window
Solution
To fit a spread in a layout view, follow these steps:
1. Follow the steps described in Setting the Spread Targeted for Edit Operations” on page 47.
2. Create a zoom command using ILayoutUIUtils::MakeZoomCmd with fit = ILayoutCon-
trolData::kFitSpread.
3. Run the zoom command.
To fit a page in a layout view, follow these steps:
1. Follow the steps described in Setting the Page viewed in a Layout Window” on page 47.
2. Create a zoom command using ILayoutUIUtils::MakeZoomCmd with fit = ILayoutCon-
trolData::kFitPage.
3. Run the zoom command.
Related APIs
zILayoutControlData
zkLayoutWidgetBoss
Setting the Zoom for the Layout Window
You can increase or decrease the magnification applied by the window.
Solution
Process one of the zoom-related commands created by ILayoutUIUtils; for example, ILayoutU-
IUtils::MakeZoomCmd.
Text 49
Text
Getting Started
Text
Getting Started
This chapter presents table-related use cases. To learn about how text layout is organized, do
the following:
zRun through the activities in “Exploring Text with SnippetRunner” on page 49, to learn how
to explore text and familiarize yourself with fundamental text-Sample Code.
zRead the “Text Fundamentals” chapter in Adobe InDesign® CS4 Programming Guide.
To solve a text-related programming problem, do the following:
zLook in this document for a use case that matches your problem.
zAs references, see the API reference documentation and the “Text Fundamentals” chapter
mentioned above.
Exploring Text with SnippetRunner
SnippetRunner is a plug-in that lets you run code snippets provided on the SDK. Several code
snippets are provided that let you explore the text-related objects in a document.
Solution
1. Run InDesign with the SnippetRunner plug-in present. For instructions on using the plug-
in, see the API documentation page for SnippetRunner.
2. Browse the sample code in the snippets you have been running.
Sample Code
zBscShpHandleShape::DrawLabelHandles in sample basic shape on the SDK
zCHMLFiltTextHelper in sample chmlfilter
zSingleLineComposer
zSnpApplyTextStyleAttributes
zSnpApplyTextStyleAttributes::ApplyFontVariant
zSnpCreateFrame
zSnpEstimateTextDepth
zSnpInsertGlyph
zSnpInspectFontMgr
zSnpInspectTextModel
Text
Getting Started
50
zSnpInspectTextStyles
zSnpManipulateInline
zSnpManipulateTextFootnotes
zSnpManipulateTextModel
zSnpManipulateTextOnPath
zSnpManipulateTextStyle
zSnpManipulateTextFrame
zSnpManipulateTextPresentation
zSnpPerformCompFont
zSnpPerformFontGroupIterator
zSnpPerformTextAttr*
zSnpTextAttrHelper
Related APIs
zICompositeFont represents a composite font.
zIDocFontMgr represents the persistent fonts in the session or document.
zIDocumentFontUsage provides a shell around IUsedFontList and IFontNames.
zHighLevelAPI::ITextWrapFacade provides functions to determine the word-wrap behavior
a particular page item forces onto text.
zIFontFamily represents a group of related styles of fonts.
zIFontGroup (not derived from IPMUnknown) represents a font family within cooltype.
zIFontInstance (not derived from IPMUnknown) is an instance of a cooltype font, character-
ized by a particular font size.
zIFontMgr on the session that is the cooltype (font subsystem) wrapper.
zIFontNames allows access to the set of fonts on which a placed asset (PDF or EPS) depends
zIFrameContentSuite/IFrameContentFacade converts a page item to a container for text and
manipulates the size of the page item relative to the text content.
zIFrameList provides a list of containers (frames) used to display the text from a single story.
zIHierarchy defines the relations of the containers within the document.
zIMissingFontSignalData provides the context for missing font responders.
zIMultiColumnTextFrame provides access to the associated story, frame list, and the range of
text displayed.
zIParcel represents an area within a frame into which some sub-text for a story can flow; for
example, a table cell or story footnote.
zIParcelList represents a set of parcels into which some sub-text for a story can flow; for
example, footnotes that span multiple page items.
Text 51
Text
Stories
zIPMFont (not derived from IPMUnknown) represents a single font within cooltype.
zITextAttrFont represents the text attribute defining the font applied to text.
zITextAttributeSuite represents the capabilities and functionality that can be applied to the
formatting of selected text.
zITextFrameColumn represents a column within a text frame.
zITextFrameOptionsSuite provides the ability to access and manipulate text frame options
(like number of columns or gutter width) on the session workspace, document workspace,
or a set of text containers.
zITextModel represents a story within the document.
zITextModelCmds provides prepackaged commands that modify a text story.
zITextParcelList provides the relationship between the rendered text (known as the wax) in a
parcel list and the parcel list.
zITextSelectionSuite represents capabilities and functions that can be applied to selected text.
zITextUtils provides higher level APIs to modify and access text content.
zIUsedFontList represents fonts used within text frames.
zIWaxStrand represents the final rendered text. It provides an iterator (IWaxStrand::New-
WaxIterator) that allows the individual lines of rendered text (wax) to be accessed.
Stories
A text story represents a single body of textual content within the application. It encompasses
the raw text and formatting applied to this text; t can be viewed as a container for all this infor-
mation. This section describes common use cases when working with text stories.
For more information see the “Text Fundamentals” chapter in Adobe InDesign CS4 Program-
ming Guide.
Accessing the Stories in a Document
A document can contain zero or more stories. You can access the set of stories contained in a
single document.
Solution
A document is represented by the kDocBoss boss class.
IStoryList on kDocBoss maintains the stories contained within a document. A document can
contain stories purely for internal use.
Use IStoryList::GetUserAccessibleStoryCount and IStoryList::GetNthUserAccessibleStoryUID
to identify and access the user-accessible stories in a document.
Text
Stories
52
Use IStoryList::GetAllTextModelCount and IStoryList::GetNthTextModelUID to access all sto-
ries in a document.
Use IStoryList::GetNthTextModelAccess to test whether a particular story is user accessible.
Sample Code
SnpInspectTextModel::ReportStories
Accessing the Stories under the Current Focus
You can get the story that maintains the current text focus.
Solution
When dealing with a selection, you need to implement a selection extension pattern, which
allows you to participate in the selection subsystem. As part of this extension pattern, you pro-
vide an add-in implementation of a concrete selection interface on the kTextSuiteBoss (and
associated add-in implementation of an abstract selection interface on the kIntegratorSuite-
Boss). For details on implementing this extension pattern, see the “Selection” chapter of Adobe
InDesign CS4 Products Programming Guide.
Use ISelectionUtils::GetActiveSelection to obtain your abstract selection, which can then pro-
vide access to the concrete selection.
ITextTarget (on kTextSuiteBoss) resides on the same boss class as your selection.
Use ITextTarget::QueryTextModel to get the text model for the selection. This interface pro-
vides other information about the text selection, like its range.
To manipulate the model through the selection, add a new suite interface onto the kTextSuite-
Boss class. This provides the mechanism required to keep actual selection types separate from
the selection architecture. For an example, see the use of the interface IDataUpdaterSuite in the
XmlDataUpdater plug-in.
Accessing a Story, given a Page Item
You can get from a page item to (potentially) the text story representing the text it contains.
Solution
Use ITextUtils::GetSelectedTextItemsFromUIDList on kUtilsBoss to extract text item entities
from a list of UID items. Specifying a non-nil UIDList for either of the out parameters causes
the associated UIDList to be populated with the set of page items containing text.
IGraphicFrameData::GetTextContentUID (the interface is on the page item) provides kInvali-
dUID if the page item is not a text container. This more direct approach is more effective if you
are interested only in whether the page item contains text, rather than getting access to the text.
Sample Code
SnpManipulateTextFrame
Text 53
Text
Stories
Creating a Story
You can create a story programmatically.
Solution
Stories are rarely created directly. Normally, they are created as a side effect of creating a text
frame.
Sample Code
SDKLayoutHelper::CreateTextFrame
Related APIs
zThe kNewStoryCmdBoss command creates a new story. It is unlikely you will have to use
this command directly.
zThe kCreateMultiColumnItemCmdBoss command creates a text frame (and the associated
story).
Deleting a Story
You can delete a story programmatically.
Solution
Stories are rarely deleted directly. Normally, a story is deleted as a side effect of deleting the last
text frame item that displays its text.
Sample Code
SnpManipulateTextFrame::DeleteTextFrame
Related API
kDeleteStoryCmdBoss deletes a text story. It is unlikely you will have to use this command
directly.
Detecting when Stories are Created
You can invoke your code on story creation.
Solution
Implement a responder extension pattern. Specifically, a custom implementation of IRe-
sponder is required (indicating a service ID of kNewStorySignalResponderService). To imple-
ment the responder, use the CResponder helper implementation.
The extension pattern requires an implementation of IK2ServiceProvider. The API provides an
implementation; the implementation ID is kNewStorySignalRespServiceImpl.
Text
Stories
54
When the responder is called, query the ISignalMgr parameter for the INewStorySignalData
interface. This interface provides access to the command that created the story and the under-
lying text model. Set the global error state from within the respond, to suppress story creation.
Detecting when Stories are Deleted
You can get called when a story is deleted.
Solution
Implement a responder extension pattern. Specifically, a custom implementation of IRe-
sponder is required (indicating a service ID of kDeleteStoryRespService). To implement the
responder, use the CResponder helper implementation.
The extension pattern requires an implementation of IK2ServiceProvider. The API provides an
implementation; the implementation ID being kDeleteStoryRespServiceImpl.
When the responder is called, query the ISignalMgr interface for the command (ICommand)
invoked for the delete operation. Set the global error state, to suppress the story deletion.
Navigating from the Story (Text Model) to a Strand
You can get from the text model (kTextStoryBoss, the main boss class that represents a story) to
a particular strand. Strands are a low-level abstraction; there are higher level APIs that allow
you to accomplish most tasks.
Solution
You can get a particular strand from the text model (ITextModel) interface on the text story
(kTextStoryBoss), using ITextModel::QueryStrand.
Sample Code
zSee SnpInspectTextModel::CountStoryOwnedItems for an example of moving from the
story (kTextModelBoss) to the owned item strand (kOwnedItemStrandBoss).
zThe SnpManipulateTextStyle::CreateParaStyle sample shows how to navigate from the story
(kTextModelBoss) to the character (kParaAttrStrandBoss) and paragraph (kCharAttr-
StrandBoss) attribute strands.
Related API
See IStrand, the signature interface for a story strand.
Text 55
Text
Story Text
Story Text
In many cases require working on the raw text in a story; for example, spell checking.
find/replace, and word count. This section includes use cases that deal with purely the text of a
story.
For details, see the “Text Fundamentals' chapter of Adobe InDesign CS4 Programming Guide.
For related APIs, see the following:
zITextModel on kTextStoryBoss is the signature interface for the story abstraction within the
application.
zIStoryList on kDocBoss maintains all stories in the document.
Accessing a Storys Raw Text Content
You can access the raw content (the body of characters) of a text story.
Solution
Use text iterators to access the raw content of a story. For an example, see SnpTextModel-
Helper::GetWideStringFromTextRange.
The compose scanner (IComposeScanner) on the story (kTextStoryBoss) supports the Copy-
Text method. For an example of its use, see SnpManipulateTextFootnotes::GetStoryThread-
Contents.
Counting the Paragraphs in a Story
You can calculate the number of paragraphs in a story.
Solution
The IComposeScanner interface, available on kTextStoryBoss, has a method (FindSurround-
ingParagraph) that determines the extent of each paragraph in the story. It can be used to scan
a story, counting the paragraphs.
You can use a similar technique with the low-level IStrand interface on the paragraph attribute
stand (kParaAttrStrandBoss) For each paragraph, a run exists on the IStrand interface on the
paragraph attribute strand (kParaAttrStrandBoss). The number of runs is equal to the number
of paragraphs. Iterate using IStrand::GetRunLength on all runs in the strand.
Sample Code
SnpInspectTextModel::ReportParagraphs
Text
Story Text
56
Counting the Words in a Story
You can calculate the number of words in a story.
Solution
The IComposeScanner interface, available on kTextStoryBoss, has a method (FindSurround-
ingWord) that determine the extent of each word in the story. It can be used to scan across a
story, counting the words.
Inserting Text into a Story
You can insert text into a story, using text commands or via a text selection.
Solution
If there is a valid text selection, use ITextEditSuite::InsertText (after testing ITextEdit-
Suite::CanEditText to determine whether the operation is allowed).
To insert characters at an arbitrary position in a story, use the command generated by IText-
ModelCmds::InsertCmd. ITextModelCmds is available on the kTextStoryBoss. Use the IText-
Model::IsModelLocked method to test whether a lock exists on the text model.
Put the inserted data into a reference counted K2::shared_ptr with type WideString, and pass it
into the InsertCmd, so the memory occupied by the data is purged when no one is referencing
it. For more information, see K2SmartPtr.h.
Sample Code
SnpManipulateTextModel::InsertText
Deleting Text from a Story
You can delete a range of text from a story, using text commands or via a text selection.
Solution
If there is a valid text selection, use ITextEditSuite::Delete to delete selected text (after testing
ITextEditSuite::CanEditText to determine whether the operation is allowed).
To delete an arbitrary range of text, use the command generated by ITextModelC-
mds::DeleteCmd. ITextModelCmds is available on kTextStoryBoss.
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Sample Code
SnpManipulateTextModel::DeleteText
Text 57
Text
Story Text
Replacing Text in a Story
You can replace a range of text with alternative text.
Solution
Use the command generated by ITextModelCmds::ReplaceCmd to replace text within a story.
Put the replaced data into a reference counted K2::shared_ptr with type WideString, and pass it
into the InsertCmd, so the memory occupied by the data is purged when no one is referencing
it. For more information, see K2SmartPtr.h.
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Sample Code
SnpManipulateTextModel::ReplaceText
Copying Text within and between Stories
You can programmatically copy text within or across text stories.
Solution
To copy text within and between stories, use the command provided by the ITextUtils::Query-
CopyStoryCommand utility facade. Variants of this API allow common use cases of text copy
to be handled; for example, copying a range from source to a range in the destination and copy-
ing the complete source story to the end of the destination story.
To copy text within the same story, source and destination references should be the same.
When specifying ranges for this operation, take care they do not overlap.
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Moving Text within and between Stories
You can programmatically move text within or across text stories.
Solution
To move text within and between stories, use the command provided by the ITextUtils::Query-
MoveStoryCommand utility facade. Variants of this API allow common use cases of text move
to be handled; for example, moving a range from source to a range in the destination and mov-
ing the complete source story to the end of the destination story.
To move text within the same story, source and destination references should be the same.
When specifying ranges for this operation, take care they do not overlap.
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Text
Story Text
58
Sample Code
SnpManipulateTextFootnotes::ConvertSelectionToFootnote shows how to move the contents
of one story thread to another, which would be the case if you want to move text cell contents
or footnotes.
Iterating across Text Story Threads in a Story
Given a story comprises one or more text story threads, each of which represents a discrete
subcomponent (like table cell text or a footnote), you may need to iterate or otherwise discover
text story threads within a story.
Solution
To be able to deal with distinct text units like table cell contents or footnotes, a hierarchy is built
on top of the simple linear model maintained by the various strands. The nodes of this hierar-
chy are represented by text story thread dictionaries (ITextStoryThreadDict, maintained on
boss classes representing the subcomponent, such as kFootnoteReferenceBoss). The root of the
hierarchy is the primary story thread. (All stories have a primary story thread; see IText-
Model::GetPrimaryStoryThreadSpan.). Story thread dictionaries maintain a mapping to a set
of text story threads (ITextStoryThread). For example, the story thread dictionary for a table is
on the table model (kTableModelBoss). It maintains the mapping to the actual text story
threads for each cell (kTextCellContentBoss). The dictionary provides the mechanism required
to iterate through all text story threads it manages.
The story (kTextModelBoss) models the inherent hierarchy using ITextStoryThreadDictHier.
Using ITextStoryThreadDictHier::NextUID, you can access all story threads in the order in
which they appear within the story.
With this background, the solution becomes apparent. For each text story thread dictionary
obtained from ITextStoryThreadDictHier::NextUID, obtain the supported set of text story
thread keys using ITextStoryThreadDict::GetFirstKey/GetNextKey before calling ITextSto-
ryThreadDict::QueryThread.
Sample Code
zSnpIterTableUseDictHier
zSnpInspectTextModel::InspectStoryThreadDicts
Obtaining the Text Story Thread for the Current Selection
If you have a valid text selection, you can determine the text story thread that maintains the
contents,
Solution
When dealing with a selection, you need to implement a selection extension pattern, which
allows you to participate in the selection subsystem. As part of this extension pattern, you pro-
vide an add-in implementation of a concrete selection interface on the kTextSuiteBoss (and
associated add-in implementation of an abstract selection interface on the kIntegratorSuite-
Text 59
Text
Story Text
Boss). For details on implementing this extension pattern, see the “Selection” chapter of Adobe
InDesign CS4 Products Programming Guide.
Use ISelectionUtils::GetActiveSelection to obtain your abstract selection, which can then pro-
vide access to the concrete selection.
ITextTarget (on kTextSuiteBoss) resides on the same boss class as your concrete selection.
ITextTarget::QueryTextModel provides the text model for the current selection. This interface
provides access to the text model as well as information on the range to which the selection
applies.
Use ITextModel::QueryStoryThread along with the index provided by the ITextTarget, to
obtain the text story thread.
Inserting an Inline Graphic into a Story
You can insert an inline graphic into the story at a particular position.
Solution
An inline graphic is represented within the text of a story using the special character
kTextChar_Inline; known as the anchor character. This character indicates to the text sub-
system that there is an inline item embedded at this position. The inline itself is represented on
the owned item strand (kOwnedItemStrandBoss). The owned item strand maintains a (persis-
tent/UID-based) reference to the actual inline item (kInlineBoss) through the IItemStrand
interface.
Two actions are required to add an inline to a story:
zAdd the anchor character to the story at the required text index.This is done using standard
text content manipulation.
zCreate and add the inline reference to the owned item strand, using the kChangeILGCmnd-
Boss command.
Sample Code
SnpManipulateInline::ChangeToInline
Modifying an Inline Object’s Position
Solution
Positioning information for an inline object is maintained on the IAnchoredObjectData inter-
face for the inline. There are many options that define the placement of the inline relative to the
anchor point within the text. You can modify the position of an inline using the IAnchoredOb-
jectSuite interface or the kChangeAnchoredObjectDataCmdBoss low level command.
Sample Code
SnpManipulateInline::ModifyAnchorPosition
Text
Story Text
60
Deleting an Inline Object
Solution
Delete the character that anchors the object into the story.
Inserting a Footnote into a Story
You can create a footnote and insert it into an existing story.
Solution
A footnote is maintained within the story as a special inline object. The character used in the
story to indicate a footnote reference is kTextChar_FootnoteMarker. The footnote is repre-
sented on the owned item strand by a reference to a kFootnoteReferenceBoss. The textual con-
tents for the footnote reside in a distinct text story thread within the story.
Three actions are required to add a footnote to a story:
1. Add the anchor character to the story at the required text index. This is done using standard
text content manipulation.
2. Create and add the footnote reference boss object to the owned item strand, using the kCre-
ateFootnoteCmdBoss command.
3. After processing, the kCreateFootnoteCmdBoss command provides the text story thread
(ITextStoryThread) for the newly created footnote in the IUIDData interface on the com-
mand boss object. Add text to this text story thread using standard text content manipula-
tion.
Sample Code
SnpManipulateTextFootnote::InsertFootnote
Deleting a Footnote from a Story
Solution
Delete the footnotes anchor character.
Sample Code
SnpManipulateTextFootnote::DeleteAllStoryFootnotes
Text 61
Text
Story Text
Determining if a Text Range is within a Footnote
Given a range or selection within a text story, there are some operations that are invalid if that
range is within a footnote. You can determine whether the range or selection is within the text
of a footnote.
Solution
Use ISelectionUtils::QueryActiveTextSelectionSuite on the kUtilsBoss to get the active text
selection (ITextSelectionSuite).
ITextSelectionSuite::IsTextSelectionInFootnote indicates whether the selection is in a footnote.
To determine whether an arbitrary text range is within the text story thread of a footnote, use
the ITextUtils::IsFootnote from the kUtilsBoss class. The API can be used to determine
whether the range is within a footnote and to get the footnote reference (kFootnoteReference-
Boss) object through the parameter list.
Determining if a Page Item can have Text along its Path
You can determine whether it is legal for a defined page item to have text along its path.
Solution
A page item can have text flowed along its path if it has one path with at least one segment with
at least two points (i.e., it cannot be a compound path or a single point). The page item cannot
be an inline item.
Sample Code
SnpManipulateTextOnPath::CanAddTextOnPath
Determining if a Page Item has Text on its Path
Solution
IPageItemTypeUtils::IsTextOnAPath on the kUtilsBoss has an API that returns true if the page
item has text along its path.
Adding Text along the Path of a Page Item
Solution
Use the kAddTextOnPathCmdBoss API command to create the text model that supports the
text on the path. This newly created text model is a candidate for traditional text content
manipulation operations.
Sample Code
SnpManipulateTextOnPath::AddTextOnPath
Text
Text Formatting
62
Adding Text to Existing Text on a Path
Solution
To navigate from a page item with associated text on its path, get the IMainTOPData interface
from the spline object. You can get the text frame associated with the text on the path using
IMainTOPData::QueryTOPFrameData. From the ITOPFrameData interface (on the kTOP-
FrameItemBoss object), you can get the ITextFrameColumn and call the QueryTextModel
interface to get the text model interface. You can manipulate the text model using the mecha-
nisms described above.
Sample Code
SnpManipulateTextOnPath::InsertTextIntoTextOnPath
Deleting the Text on a Path
Solution
To delete the text on a path for a spline item, use the kTOPDeleteCmdBoss API command.
Specify the spline to be processed on the item list.
Sample Code
SnpManipulateTextOnPath::DeleteTextOnPath
Inserting Page Numbering and Title Heading into a Story
Solution
The text composition engine provided with the application automatically replaces special char-
acters in the text stream with page numbering and/or section header text (the exact format
defined by the preferences). For page numbering, insert the kTextChar_PageNumber character
into the text story. For headings, insert the kTextChar_SectionName special character into the
text model.
Text Formatting
This document contains use cases related to formatting text and managing text styles within
the application.
Text is formatted to give it a particular look, like underlined or in a particular font face. The
desired look of text can be described by a set of attributes; for example, a point size or text
color. Attributes are defined to be either character or paragraph based. Character attributes can
be applied to text at any granularity, from a single character to the entire story. Paragraph
attributes are settings that work at the granularity of a paragraph (for example, hyphenation
behavior or horizontal justification).
Text 63
Text
Text Formatting
Generally, attributes are grouped together to describe a common theme (for example, a head-
ing or body text); these themes are called styles. Attributes also can be applied to text indepen-
dently of any applied style. These attributes are said to be overrides, as they override the
definition of that attribute in the style.
A style is a mechanism for identifying groups of attributes. In the application, character and
paragraph styles are supported (along with table styles, which are not considered here). Char-
acter styles contain only character-based attributes. Paragraph styles can contain either charac-
ter- or paragraph-based attributes. The style can be queried to determine its type
(IStyleInfo::GetStyleType). All text has a character and paragraph style applied to it (repre-
sented on the character and paragraph attribute strands, respectively).
For more information, see the “Text Fundamentals” chapters of Adobe InDesign CS4 Program-
ming Guide.
Accessing the Set of Supported Styles
Styles can exist for all documents on a session or a particular document. They are accessed
through the workspace and are modeled within the application using the persistent kStyleBoss.
Session workspace styles are inherited into the document workspace (thus preventing the style
not being available at a later date or on another machine).
You can access the set of styles available to a particular document.
Solution
Styles can exist on either the session or document workspace. Session workspace styles are
available for all documents; document workspace styles are available only for that document.
The workspace boss classes support two implementations of the IStyleGroupManager inter-
face, IID_IPARASTYLEGROUPMANAGER for paragraph styles and
IID_ICHARSTYLEGROUPMANAGER for character styles. The interface provides the
GetRootHierarchy() API, which returns a pointer to IStyleGroupHierarchy at the root level.
Use IStyleGroupHierarchy to iterate across the supported styles.
Sample Code
SnpInspectTextStyles::Inspect
Accessing a Style using its Path
The IStyleGroupManager::FindByName(PMString fullPath) method returns the UID of a
kStyleBoss in the style group hierarchy specified in the fullPath. The fullPath to pass into the
method is the “internal” path name. Normally, you cannot construct an internal path name
using a string literal, because the internal path uses a path delimiter that is not accessible by
keyboard. This is necessary because a style name can include most of the common path delim-
iters (like “:”and “/”). A main reason for this is to provide backward compatibility for styles cre-
ated before the style group concept was introduced in InDesign CS4. Previously, many users
named styles with “:” to better organize their styles. Therefore, if you construct a PMString
path with string literals and pass it into the IStyleGroupManager::FindByName(PMString full-
Text
Text Formatting
64
Path) method, you are asking IStyleGroupManager to find a style with the passed-in name at
the root level. For example, if you pass “My Group:Style 1” (as PMString) into FindByName(),
IStyleGroupManager still treats the whole string as the style name, not as the path (as you
expect). This string literal is used to find the style with the name “My Group:Style 1” on the
root level.
To use the IStyleGroupManager::FindByName(PMString fullPath) method, pass in a valid
internal path for a style. To get the internal path, use the IStyleGroupHierarchy::GetFullPath()
method. IStyleGroupHierarchy is aggregated on three bosses: kStyleGroupHierarchyBoss,
kStyleGroupBoss, and kStyleBoss. This means to find a style by name using a internal full path,
you need to have previously accessed the style or style group. For example, if you have a UID
for a style, you can use the UID to query its IStyleGroupHierarchy and ask for its internal full
path using GetFullPath(); later, you can use the path to find the style again.
Solution
Use SnpApplyTextStyleAttributes::CreateParaStyle.
Accessing a Style using its Name and Parent Style Group UID
As explained in Accessing a Style using its Path” on page 63, there is no easy way to specify a
path to find a style. IStyleGroupManager defines an overloaded FindByName(UID parent,
const PMString& name), so if you have access to a style group UID and you know the name of
style you are looking for, you can use this method to find the corresponding style. It returns the
UID of the style whose name matches the passed name within the specified parent style group
node.
Solution
Use SnpApplyTextStyleAttributes::ApplyParaStyle.
Determining a Style’s Type
You can determine the style a particular kStyleBoss represents.
Solution
From the kStyleBoss, use the IStyleInfo::GetStyleType API.
Determining a Style’s Parent Style
InDesign has the concept of a root style. All other styles inherit from the root style, maintaining
within their definition only how they differ from their parent. For a particular style, you can
determine its parent; i.e. the style on which it is based.
Solution
IStyleInfo on kStyleBoss provides the API IStyleInfo::GetBasedOn. This provides either the
parent style UID or kInvalidUID if the style is the root.
Text 65
Text
Text Formatting
Determining the Value of an Attribute within a Style
You can determine what a style means to a particular attribute; that is, what value for a particu-
lar attribute would be applied to text (as long as there are no local overrides).
Solution
Since styles do not maintain a full set of attributes (they record only the differences from the
style on which they are based), you can determine the setting for a particular attribute by
obtaining the list of attributes supported by the style (ITextAttributes). Querying this interface
for the particular attribute of interest (ITextAttributeList::QueryByClassID, say) returns either
the attribute (if this style specifies it) or nil. In the latter case, the parent style needs to be inter-
rogated to determine whether it specifies the attribute. Continue until the attribute is found.
For paragraph styles, the attribute is found at some point; the terminal case is the root style. For
character styles, the root style is empty, deferring the attribute values to the paragraph style. In
this case, if the attribute is not defined by any (parent) character style, the root paragraph style
provides the value.
Creating a New Style
You can create a new character or paragraph style.
Solution
Use kCreateParaStyleCmdBoss or kCreateCharStyleCmdBoss. The item list for each of these
commands identifies the workspace the style is to be added to (generally the session or docu-
ment workspace). Beginning in InDesign CS4, a new Interface IStylePositionInfo is added to
kCreateParaStyleCmdBoss and kCreateCharStyleCmdBoss. IStylePositionInfo allows the style
to be created inside a style group, as explained in the “Text Fundamentalschapter of Adobe
InDesign CS4 Programming Guide. To create a style group, use kCreateStyleGroupCmdBoss.
Sample Code
See SnpManipulateTextStyle::CreateParaStyle for an example of how to create a new paragraph
style inside a style group. This sample provides its own implementation for generating a unique
style name; however, the style utility interface on the utils boss class provides an API that pro-
vides this functionality (IStyleUtils::CreateUniqueName).
Modifying an Existing Style
You can modify a style by either modifying the attributes the style represents or changing some
aspect of the style, like its name.
Solution
Changes to styles are handled through the kEditTextStyleCmdBoss command. The UIDData
interface on this boss class identifies the style being manipulated. The ITextAttributes interface
identifies the list of attributes that will exist in the style after the command is processed (this is
an absolute list, so to modify an existing attribute on the style, representing the attribute within
Text
Text Formatting
66
this list will update it in the style). The IStyleInfo interface defines the metadata (like style
name), the style it is based on, and what the next style should be (for paragraph styles).
There are utility methods in IStyleUtils (on the UtilsBoss) that construct the kEditTextStyleC-
mdBoss commands. These methods allow the caller to determine sets of attributes that should
be added or deleted from the style (rather than forcing them to define an absolute set that is left
in the style once the command completes).
Related API
IStyleUtils::CreateEditStyleCmd
Deleting a Style
You can delete a style from a style name table. There are implications for text already formatted
with the deleted style.
Solution
Use the kDeleteParaStyleCmdBoss or kDeleteCharStyleCmdBoss command. The command
boss supports IBoolData. Setting this interface indicates formatting should not be stripped
from text using the style; the formatting is maintained by a set of local attribute overrides. The
IUIDData interface (identified with the ID IID_IREPLACEUIDDATA interface) allows an
alternate style to be specified as a replacement style. The style to be deleted is identified
through the IUIDData (default IID) interface. The item list identifies the workspace from
which the style is deleted.
Sample Code
SnpManipulateTextStyle::DeleteParaStyle
Applying a Style to Text
You can apply a style to a range of text or the current selection.
Solution
If you are dealing with a selection, use ISelectionUtils::QueryActiveTextSelectionSuite on the
kUtilsBoss to get the active text selection (ITextSelectionSuite). The same boss class supports
the ITextAttributeSuite interface.
Use ITextAttributeSuite::ApplyStyle to set the new style or revert the style back to the root style
(in this case, with the option to leave the formatting intact as a set of attribute overrides).
To apply a style to an arbitrary range of text, use the command provided by ITextModelC-
mds::ApplyStyleCmd (the ITextModelCmds interface is available on the kTextStoryBoss class).
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Text 67
Text
Text Formatting
Sample Code
See SnpApplyTextStyleAttributes::ApplyParaStyle for an example of using ITextAttributeSuite.
Removing a Style from Text
You can remove a style from a text selection or an arbitrary text range.
Solution
If you are dealing with a selection, use ISelectionUtils::QueryActiveTextSelectionSuite on the
UtilsBoss to get the active text selection (ITextSelectionSuite). The same boss class supports the
ITextAttributeSuite interface. This interface has the API ApplyStyle, which can be used to set
the new style as the root style, in effect removing the style.
To remove a style from an arbitrary range of text, use the command provided by ITextModelC-
mds::UnapplyStyleCmd (the ITextModelCmds interface is available on the kTextStoryBoss
class).
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Sample Code
See SnpApplyTextStyleAttributes::ApplyParaStyle for an example of using ITextAttributeSuite.
Obtaining the Style of Text
You can determine the character or paragraph style for a particular text position (identified
through a selection or arbitrary text index).
Solution
If you have a selection, obtaining the text attribute suite interface (ITextAttributeSuite) from
the text selection (ISelectionUtils::QueryActiveTextSelectionSuite) allows you to determine
how many styles are in the selection (using ITextAttributeSuite::CountParagraphStyles and
ITextAttributeSuite::CountCharacterStyles), and iterate through them (using ITextAttributeSu-
ite::GetNthParagraphStyle and ITextAttributeSuite::GetNthCharacterStyle).
To get the style from an arbitrary position in the story, navigate to the appropriate strand—
either the paragraph (kParaAttrStrandBoss) or character (kCharAttrStrandBoss) attribute
strands. Obtain the IAttributeStrand interface, which supports the IAttributeStrand::Get-
StyleUID method, returning the style for a particular text position.
Sample Code
See SnpManipulateTextStyle::UpdateParaStyle for an example of accessing the style at a given
text index.
Text
Text Formatting
68
Obtaining the Value of an Attribute applied to Text
You can access the single named attribute that applies to a text selection or a text index or
range.
Solution
If you have a selection, obtaining the text attribute suite interface (ITextAttributeSuite) from
the same boss class as the text selection (ISelectionUtils::QueryActiveTextSelectionSuite) pro-
vides you with methods that expose the state of a particular attribute (see ITextAttributeSu-
ite::FeatureState). For example, ITextAttributeSuite::GetCapsModeState indicates whether a
certain mode applies to all the text, none of the text, or some of the text (if the attribute changes
along the selection).
To determine whether there is an attribute override, use ITextAttributeSuite::CountAttributes,
passing in the ClassID for the attribute of interest. An attribute is provided for each time the
attribute value changes across the range of the selection. ITextAttributeSuite::QueryAttributeN
provides the set of attributes that apply to the selection for a particular attribute class.
To get the attribute value from an arbitrary position in the story, use the IComposeScanner
interface (on kTextStoryBoss). The method IComposeScanner::QueryAttributeAt provides the
attribute that applies to the identified text index.
There is an iterator class (TextAttributeRunIterator) that allows the set of attributes that apply
to a range of text to be accessed, dealing with the changes in attributes that can occur across
ranges.
Sample Code
zSee SnpApplyTextStyleAttributes::CycleSmallAllCaps for an example.
zSee SnpInspectTextModel::InspectStoryPointSizes for an example of using a TextAt-
tributeRunIterator to access the attributes in a range of text.
Modifying the Value of an Attribute for Text
You can modify an attribute applied to a text selection or text range.
Solution
If you have a selection, obtaining the text attribute suite interface (ITextAttributeSuite) from
the same boss class as the text selection (ISelectionUtils::QueryActiveTextSelectionSuite) pro-
vides you with methods that allow you to modify the format of the selection (for example,
ITextAttributeSuite::ToggleItalic, or ITextAttributeSuite::IncrementPointSize). The suite also
provides mechanisms for setting the value of attributes that have non-exotic data requirements.
For example, use ITextAttributeSuite::SetInt16Attribute to specify that an override for an
attribute of a particular type should be applied to the text, with a particular value. For attributes
with more exotic data requirements, use ITextAttributeSuite::ApplyAttribute, though the onus
for the creation of the attribute falls on the client.
Before manipulating the selection in this way, test that the operation is valid (ITextAttributeSu-
ite::CanApplyAttributes).
Text 69
Text
Text Formatting
To modify the attribute given an arbitrary range of text, use ITextModelCmds interface (on
kTextStoryBoss), which provides a command through the ITextModelCmds::ApplyCmd API
that modifies the attributes. This command expects a K2::shared_ptr. The AttributeBossList
that defines the attributes to be applied should be allocated on the heap and wrapped in a
K2::shared_ptr. This implements reference counting for the attribute list and automatically
deletes it when it is no longer used.
It is important to apply attributes to the correct strand: paragraph attributes should be applied
to the paragraph-attribute strand, and character attributes should be applied to the character-
attribute strand. For example, it would make no sense to try to set the justification of text on
the character-attribute strand, as justification is a paragraph attribute. Likewise, it would not
make sense to set the point size of text on a paragraph strand.
Although you cannot apply character-attribute overrides directly to the paragraph-attribute
strand, you can do so indirectly by defining a paragraph style with the character-attribute over-
ride defined, and applying this style to the paragraph-attribute strand.
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Sample Code
zSee SnpApplyTextStyleAttributes::ApplyFontVariant for an example of using ITextAt-
tributeSuite::ApplyAttribute.
zSee SnpTextModelHelper::ApplyOverrides for an example of using ITextModelC-
mds::ApplyCmd.
Clearing Attribute Overrides for Text
You can remove local formatting overrides for a text selection or text range (leaving the text
formatted to the specification of whatever style is applied).
Solution
If you have a selection, obtaining the text attribute suite interface (ITextAttributeSuite) from
the same boss class as the text selection (ISelectionUtils::QueryActiveTextSelectionSuite) pro-
vides you with methods that allow you to remove character-attribute overrides (ITextAttribute-
Suite::ClearCharacterOverrides), paragraph-attribute overrides
(ITextAttributeSuite::ClearParagraphOverrides), or both (ITextAttributeSuite::ClearAllOver-
rides).
Before removing the formatting information, test the capability using ITextAttributeSu-
ite::CanRemoveFormatting.
To remove all the attributes that are overridden given an arbitrary range of text, use the IText-
ModelCmds interface (on kTextStoryBoss) which provides a command through the ITextMod-
elCmds::ClearOverridesCmd API that removes all specified overrides for a particular strand.
To specify all overrides, navigate to the stand of interest (ITextModel::QueryStrand on kText-
StoryBoss), obtain the IAttributeStrand interface, and use IAttributeStrand::GetLocalOverrides
to obtain a list of all attribute overrides that exist at a particular text index.
Text
Text Formatting
70
Before performing the modification, check the model to ensure it is not locked (IText-
Model::IsModelLocked).
Sample Code
See SnpTextModelHelper:ClearOverrides for an example of using ITextModelC-
mds::ClearOverridesCmd.
Determining the Type of an Attribute
Paragraph attributes should be applied only to the paragraph-attribute strand; character
attributes, to the character-attribute strand. You can determine the type of an attribute.
Solution
The signature interface for an attribute boss class is IAttrReport. It supports a method, IsPara-
graphAttribute, that indicates whether the attribute is a paragraph attribute.
Defining a Custom Text Attribute
Most attributes control some aspect of the final appearance of rendered text, like point size or
font. The composition engines delivered with the application understand and interpret these
attributes when rendering the text. You can add custom text attributes to the application using
the text attribute extension pattern.
A text-adornment extension pattern can be used to decorate the text; it provides a hook into
the drawing of the text. Custom text attributes are used to control the drawing behavior of the
adornment for ranges of text.
Text attributes also can be used to give a range of text special meaning; that is, overlay use-spe-
cific information on the text story for ranges of characters. For example, imagine you want
some text in a story to be variable and replaced with text from database records when doing a
print run.
Sometimes, you want to add another attribute, something that can be applied to text to give the
rendered appearance a specific effect. You need to add a custom attribute for this (in fact, you
also need to define a custom composition engine, as there is no mechanism to direct the sup-
plied composers to interpret custom attributes).
Solution
Implement a custom text-attribute extension pattern. To do this, provide an implementation of
the IAttrReport interface in a boss class. Further, if the attribute has some meaning for tagged
text import/export, provide an implementation of IAttrImportExport.
Sample Code
See the BasicTextAdornment sample from the SDK for an example of using a custom text
attribute to control the behavior of a text adornment.
Text 71
Text
Text Containers
Text Containers
Raw text content is presented to the user through a process known as composition. Raw text
content is defined as the Unicode text along with some idea how it is to be displayed. The pro-
cess of composition needs some notion of where to place the text. It works with containers,
which are parcels into which the text can be placed. Several types of containers are supported:
zText frames, like those created using theType Tool.
zText on the path of a spline (text on a path), such as you could create using the “Type on a
Path Tool.
zText in a foot note.
zText within a table cell (this is covered in the tables documentation).
A story (i.e., a discrete body of textual work) can be spread across multiple columns of a page
element. The story can have embedded tables and footnote references, and it can be spread
across several page elements (on different pages of the document).
This section presents use cases for interacting with text containers and controlling options that
apply to them.
For more information, see Adobe InDesign CS4 Programming Guide.
Creating a Text Frame
You can create a page item to hold text.
Solution
Use the kCreateMultiColumnItemCmdBoss command. To specify the characteristics of the
new text item, use the IMultiColumnData and ICreateFrameData interfaces.
Sample Code
zSDKLayoutHelper::CreateTextFrame
zSnpCreateFrame::CreateTextFrame
Converting a Page Item into a Text Frame
You can modify a page item so it can be a container for text.
Solution
Given a selection, follow these steps:
1. Obtain the IFrameContentSuite, using ISelectionUtils::QuerySuite on the kUtils boss class.
2. Check the capability by calling IFrameContentSuite::CanConvertItemToText
Text
Text Containers
72
3. Use IFrameContentSuite::ConvertItemToText to convert selected items that are candidates
for conversion.
Given an arbitrary set of page items, follow these steps:
1. Use IFrameContentFacade::CanConvertItemToText (an interface on the kUtils boss class)
to test the capability
2. Use IFrameContentFacade::ConvertItemToText to convert items that are candidates for
conversion.
Sample Code
SnpManipu lateTextPresent ation::C onve r tToText
Examining the Characteristics of a Text Frame
Solution
Given a selection, follow these steps:
1. Obtain the interface using ISelectionUtils::QuerySuite on the kUtils boss class.
2. Use ITextFrameOptionsSuite::GetTextFrameOptionsData to provide a reference to the
ITextFrameOptionsData interface, which can be interrogated for the text frame options.
Given an arbitrary set of page items, do the following:
1. Navigate to the kMultiColumnItemBoss object (child of kSplineItemBoss via IHierarchy).
2. Use ITextColumnSizer to provide access to attributes of the frame (gutter width, inset,
number of columns etc.).
Sample Code
SnpManipulateTextFrame::InspectTextFrame
Modifying the Characteristics of a Text Frame
Solution
Given a selection, follow these steps:
1. Obtain the interface using ISelectionUtils::QuerySuite on the kUtils boss class.
2. Use ITextFrameOptionsSuite::CanApplyTextFrameOptions to test the capability to modify
options on the selection.
3. Use ITextFrameOptionsSuite::SetTextFrameOptionData to manipulate the options on the
frame. This API takes a reference to the ITextFrameOptionsData interface. The API pro-
vides a boss class (kObjStylesTFOptionsCollectDataBoss) that can be used to hold the text
frame options for this API.
Text 73
Text
Text Containers
Given an arbitrary set of page items, there is no one way to manipulate text frame options. You
can do the following:
zChange the number of columns with kChangeNumberOfColumnsCmdBoss.
zManipulate the text inset with kSetTextInsetCmdBoss.
zModify the column gutter with kSetColumnGutterCmdBoss.
Sample Code
zSnpManipulateTextFrame::IncrementTextInset
zSnpManipulateTextPresentation::IncrementFrameColumns
Deleting a Text Frame
Solution
You delete page items holding text like any other page item. If the text is linked through other
page items, it continues to exist (reflowing through linked items), and no text is deleted. If the
text is contained only within the single page item, deleting the page item causes the associated
text objects to be deleted.
To delete an arbitrary page item, use kDeleteCmdBoss.
Sample Code
SnpManipulateTextFrame::DeleteTextFrame
Detecting if a Page Element is a Text Frame
Arbitrary page items can contain text, and the relationship between container and text is main-
tained as an association between two sets of objects. You can determine whether a page item
has this association.
Solution
Call IPageItemTypeUtils::IsTextFrame.
Sample Code
SnpManipulateTextFrame::IsTextFrame code snippet
Text
Text Containers
74
Navigating to the Text Frame for a Page Item
Suppose you have a reference to a page element (that could have been obtained through a selec-
tion, for instance). You can navigate to the associated text container object(s) for that page ele-
ment, assuming they exist.
Solution
1. Obtain the hierarchy (IHierarchy) interface from the page item object. The text container
objects are maintained as part of the page item hierarchy.
2. Child 0 (zero) on the hierarchy is a column object (kMultiColumnItemBoss) that represents
the set of text columns an individual page item can have.
3. With respect to the hierarchy (IHierarchy) on the multi-column object, each child is an
individual frame (kFrameItemBoss), representing one column of text in the page item.
4. To get the parcel related to a particular frame, use the IParcel interface on the frame item
boss object (kFrameItemBoss).
5. If you are interested in other parcels associated with the frame (for example, for a footnote),
note the frame (kFrameItemBoss) object does not maintain the association. A list of all par-
cels used to display text for a particular story is provided through the frame list boss object
(kFrameListBoss). You can obtain this interface from the frame item (kFrameItemBoss)
using IParcel::QueryParcelList.
Sample Code
SnpManipulateTextFrame::InspectTextFrame code snippet
Navigating to the Text Frame for Text on a Path
Suppose you have a reference to a page element (that could have been obtained through a selec-
tion, for instance). You can navigate to the associated text container object(s) for text that
might appear on the items path.
Solution
1. Obtain the hierarchy (IHierarchy) interface from the page item object (kTOPSplineItem-
Boss). The text container objects are maintained as part of the page item hierarchy.
2. Child 0 (zero) on the hierarchy is a column object (kMultiColumnItemBoss) that represents
the set of text columns an individual page item can have.
3. With respect to the hierarchy (IHierarchy) on the multi-column object, there should be one
frame item (kTOPFrameItemBoss) object.
4. To get the parcel related to a particular frame, use the IParcel interface on the frame item
boss object (kFrameItemBoss).
Text 75
Text
Text Containers
Sample Code
SnpManipulateTextFrame::InspectTextFrame code snippet
Finding the Range of Characters displayed by a Text Frame
You can determine the range of the primary story thread displayed in a text frame. For details
on accessing the raw text for a range, see “Story Text” on page 55.
Solution
The text must be fully composed. Follow these steps:
1. Use IMultiColumnTextFrame::TextSpan to get the number of characters from the primary
story thread that exist in the frame.
2. Use IMultiColumnTextFrame::TextStart to get the index within the primary story thread of
the first character in the text frame.
The range is from the text start until the text start plus the text span. It may include the final
terminating character of the primary story thread. The range of characters relates to all col-
umns of text in the text frame. If the ITextFrame interface being queried is from a frame item
(kFrameItemBoss), the range of characters relates to one column.
Sample Code
SnpManipulateTextFrame::GetTextFrameTextRange
Finding the Page Item that displays a given TextIndex
You can get the text frame (kFrameItemBoss) for a given text index within a story.
Solution
The text must be fully composed. Follow these steps:
1. Use ITextModel::QueryFrameList to get the frame list (IFrameList) on the frame list boss
object (kFrameListBoss).
2. Use IFrameList::QueryFrameContaining to get the text frame (ITextFrameColumn) for the
frame boss object (kFrameItemBoss).
3. Use IHierarchy::QueryParent to get the multi-column frame item (kMultiColumnItem-
Boss). Use the equivalent call on the multi-column item to get the page item (kSplineItem-
Boss).
NOTE:The index need not belong to the primary story thread; it could reference text within
another story thread, like a table cell or footnote.
Sample Code
SnpManipulateTextFrame::QueryTextFrameContaining
Text
Text Containers
76
Finding the Story associated with a Parcel
Given a parcel (IParcel), you can determine the story with which it is associated.
Solution
The text must be fully composed. Follow these steps:
1. Use IParcel::QueryFrame on the parcel object to get the text frame interface (ITextFrame-
Column) on the text frame boss object (kFrameItemBoss) with which the parcel is associ-
ated.
2. Use ITextFrameColumn ::QueryTextModel to get the text model for the text that flows in
the text frame.
Alternatively, navigate using the text parcel list (ITextParcelList), as follows:
1. Use IParcel::QueryParcelList on the parcel object to get the parcel list (IParcelList) that
maintains the relationship for associated parcels.
2. Use ITextParcelList::GetTextModelRef to get the UIDRef for the text model (kTextModel-
Ref) associated with the parcel. ITextParcelList is on the same boss object as the IParcelList
interface.
Sample Code
SnpEstimateTextDepth::GetParcelTextRange code snippet
Finding the Range of Text displayed by a Parcel
You can determine the range of a particular text story displayed in a particular parcel (IParcel).
Solution
The text must be fully composed. Follow these steps:
1. Use IParcel::GetParcelKey to obtain the parcel key.
2. Use IParcel::QueryParcelList on the parcel object to get the parcel list (IParcelList) that
maintains the relationship between text story threads and associated parcels.
3. Get the text parcel list interface (ITextParcelList) from the same boss object.
4. ITextParcelList::GetTextRange returns the range of text in the specified parcel.
Sample Code
zSnpTextModelHelper::GetParcelTextRange code snippet
zSnpTextModelHelper::GetWideStringFromParcel code snippet
For details on accessing the raw text for a particular range, see “Story Text” on page 55.
Text 77
Text
Text Containers
Finding the Parcel that displays a TextIndex
Given a particular text story (ITextModel), you can find the parcel (IParcel) into which the text
from a particular index in the text model is composed.
Solution
The text must be fully composed. Follow these steps:
1. Use ITextModel::QueryTextParcelList to get the text parcel list (ITextParcelList).
2. ITextParcelList::GetParcelContaining returns the key for the parcel you need.
3. Get the parcel list interface (IParcelList) from the same boss object as ITextParcelList.
4. IParcelList::GetParcelContaining returns the required parcel (IParcel).
Sample Code
SnpTextModelHelper::QueryParcelContaining code snippet
Detecting Overset Stories
Figure 1 shows a story that is overset: the combined area of all linked frames associated with the
story is not large enough to contain the text in the story. The figure shows a story associated
with two linked frames. Both frames are overset, as is the story. You can determine whether a
story is overset.
FIGURE 1An Overset Story with Two Frames
Text frame is overset Text frame is overset
Story is overset
Text
Text Containers
78
Solution
The text must be fully composed. Follow these steps:
1. Navigate to the frame list boss (kFrameListBoss), in one of two ways. If dealing with a page
item, you can use IHierarchy::QueryChild, then IMultiColumnTextFrame::QueryFrameList
from the multi-column boss object (kMultiColumnItemBoss). If dealing with a text story
(kTextStoryBoss), you can use ITextModel::QueryFrameList.
2. Use ITextUtils::IsOverset (the interface is available on the kUtilsBoss) to determine whether
all the text is represented in a parcel. If only the final (required) carriage return is overset,
the text is not defined to be overset.
Sample Code
SnpEstimateTextDepth::IsStoryOverset code snippet
Detecting Overset Text Frames
Figure 1 shows two linked text frames associated with a story. Both are said to be overset, as the
text in the story overruns each frame. You can determine whether a text frame is overset.
Solution
If the frame has a span of 0 (zero), it is underset (i.e., no characters flow into it from a preceding
frame). If the final character of the primary story thread, not including the mandatory carriage
return, does not exist in the frame, it is overset.
The text must be fully composed. Follow these steps:
1. Use IMultiColumnTextFrame::TextSpan to get number of characters in the frame. If this is 0
(zero), the frame is underset.
2. Use IMultiColumnTextFrame::TextStart to get the starting character for the primary story
thread within the frame. Add the text span to get the primary story thread index for the last
character displayed in the text frame.
3. Use IMultiColumnTextFrame::QueryTextModel to get the text model (ITextModel) inter-
face on the text story (kTextStoryBoss).
4. Use ITextModel::GetPrimaryStoryThreadSpan to get the number of characters in the pri-
mary story thread. If this number is greater than the index of the last character in the frame
(calculated above), the text frame is overset.
Sample Code
SnpEstimateTextDepth::IsTextFrameOverset code snippet
Text 79
Text
Text Containers
Detecting Overset Parcels
You can determine whether the characters in a particular story thread extend beyond a partic-
ular parcel (IParcel).
Solution
If the parcel has a span of 0 (zero), it is underset (i.e., no characters flow into it from a preced-
ing parcel). If the final character of the primary story thread, not including the mandatory car-
riage return, does not exist in the parcel, it is overset.
This solution depends on the text being fully composed.
To detect is a parcel is overset, follow these steps:
1. Use IParcel::GetParcelKey to obtain the parcel key.
2. Use IParcel::QueryParcelList on the parcel object to get the parcel list (IParcelList) that
maintains the relationship between text story threads and associated parcels.
3. Get the text parcel list interface (ITextParcelList) from the same boss object.
4. Use ITextParcelList::GetParcelIsEmpty to determine whether the parcel is empty. If so, is
underset.
5. Use ITextParcelList::QueryStoryThread to get the story thread (ITextStoryThread) that rep-
resents the text in the parcel list.
6. Use ITextStoryThread:GetTextSpan to get the number of characters in the text story thread
that is composed into this particular parcel list.
7. Use ITextParcelList::GetParcelContaining to access the parcel key that contains the final
character for the text story thread. If this parcel key differs from the parcel key obtained
above, the parcel is overset.
Sample Code
SnpEstimateTextDepth::IsParcelOverset code snippet
Determining if Text is “On a Path” (TOP)
Given a particular index, you can determine whether the composed text referred to by the
index falls on a spline (rather than within a standard text frame (kFrameItemBoss).
Solution
The text must be fully composed. Follow these steps:
1. Obtain the frame item (in this case a kTOPFrameItemBoss) for the index as you would any
other frame item. See “Finding the Page Item that displays a given TextIndex” on page 75.
2. Test the frame item for the signature interface, ITOPFrameData.
Text
Text Containers
80
Threading Text Frames
Given two text containers (IMultiColumnTextFrame), you can link them to allow one story to
be associated with both.
Solution
Use ITextUtils::LinkTextFrames to link the two frames. If you need finer control over what
happens with the text contained within the pre-existing text frames, first manipulate the text
content in the required fashion (see “Story Text” on page 55), then use the kTextLinkCmdBoss
to link the frames. This command requires the kMultiColumnItemBoss for both frames to be
linked to be placed on the command’s item list.
Sample Code
zSnpManipulateTextFrame::CanThreadTextFrames code snippet
zSnpManipulateTextFrame::ThreadTextFrames code snippet
Unthreading Text Frames
Given two linked text frames (IMultiColumnTextFrame), you can unlink them.
Solution
Use kTextUnlinkCmdBoss, passing in the frame the break is to occur after, on the command
item list.
Sample Code
zSnpManipulateTextFrame::CanUnlinkTextFrame code snippet
zSnpManpulateTextFrame::UnlinkTextFrames code snippet
Navigating between Threaded Text Frames
Given a text frame (IMultiColumnTextFrame), you can navigate to the next frame through
which the primary story thread flows.
Solution
1. Use IMultiColumnTextFrame ::QueryFrameList to get the list of frames.
2. IFrameList::GetFrameIndex returns the index of the current frame in the list of frames.
3. Use IFrameList::GetFrameCount to get the total number of frames in the list.
4. Use IFrameList::QueryNthFrame to get a specified frame.
Sample Code
SnpManipulateTextFrame::InspectFrameList code snippet
Text 81
Text
Text Containers
Modifying Text Frame Options
A text frame has a set of associated options that describe how the text flows within the con-
tainer, including the following:
zNumber of columns.
zColumn width.
zGutter (space between columns) width.
You can modify the options for a text frame.
Solution
To change the frame options for the current selection, use the ITextFrameOptionsSuite suite.
For example, to increment the number of columns, follow these steps:
1. Use ISelectionUtils::QuerySuite (on the kUtilsBoss class) to get the text frame options suite
interface (ITextFrameOptionsSuite).
2. Use ITextFrameOptionsSuite::GetColumnsAndGutter to get the number of existing col-
umns.
3. Use ITextFrameOptionsSuite::CanApplyTextFrameOptions to test the ability to modify the
frame options.
4. This suite uses a data object to maintain the collection of options available for text frame.
The API provides an implementation that can be used (see ITextFrameOptionsData inter-
face available on kObjStylesTFOptionsCollectDataBoss). Create this boss object, and set the
required state.
5. Use ITextFrameOptionsSuite::SetTFOColumns to apply the new columns value defined in
the data object to the selection.
To change the frame options for an arbitrary text frame (IMultiColumnTextFrame on kMulti-
ColumnItemBoss), use API-supplied commands. See Figure 2).
Text
Text Containers
82
FIGURE 2Commands that Mutate Text Frame Options
Sample Code
zSee the SnpManipulateTextFrame::IncrementNumberOfColumns code snippet for an
example of using lower-level commands to modify text-frame options.
Modifying the Default Text Frame Options
Description
A text frame has a set of associated options that describe how the text flows within the con-
tainer. These options exist on the workspace (the session workspace, which is inherited by new
documents on the document workspace). They include the following:
zNumber of columns.
zColumn width.
zGutter (space between columns) width.
«boss class»
kSplineItemBoss
«boss class»
kMultiColumnItemBoss
1
1
«boss class»
kFrameItemBoss
1
1..*
ITextInset
ITextColumnSizer
IMultiColumnTextFrame
Text frame
IBoolData
IID_IIGNOREWRAP
The item list for the commands given below
should refer to the kSplineItemBoss objects
of the text frames to be changed.
«boss class»
kSetTextInsetCmdBoss
«boss class»
kChangeNumberOfColumnsCmdBoss
«boss class»
kSetFrameMinFirstLineOffsetCmdBoss
«boss class»
kSetMaxVJInterParaSpaceCmdBoss
«boss class»
kSetFrameVertJustifyCmdBoss
«boss class»
kSetFrameFirstLineOffsetMetricCmdBoss
«boss class»
kSetIgnoreWrapCmdBoss
Text 83
Text
Text Containers
You can modify the default options for a text frame.
Solution
Use the ITextFrameOptionsSuite suite. For example, to increment the number of columns, fol-
low these steps:
1. Use ISelectionUtils::QuerySuite (on the kUtilsBoss class) to get the text frame options suite
interface (ITextFrameOptionsSuite). With no open document, the suite applies to the ses-
sion workspace defaults. With a document open and no selection, the suite applies to the
document workspace defaults.
2. Use ITextFrameOptionsSuite::GetColumnsAndGutter to get the number of existing col-
umns.
3. Use ITextFrameOptionsSuite::CanApplyTextFrameOptions to test the ability to modify the
frame options.
4. This suite uses a data object to maintain the collection of options available for text frame.
The API provides an implementation that can be used (see ITextFrameOptionsData inter-
face available on kObjStylesTFOptionsCollectDataBoss). Create this boss object, and set the
required state.
5. Use ITextFrameOptionsSuite::SetTFOColumns to apply the new columns value defined in
the data object to the selection.
Alternatively, to modify the default settings regardless of whether a document is open (for
example, to target a particular document or the session default value rather than the front-most
document default value), use kSetFramePrefsCmdBoss. See Figure 3, which shows the relation-
ships between workspaces and text-frame options.
FIGURE 3Commands that Mutate and Use Default Text-Frame Options
«boss class»
kDocWorkspaceBoss
«boss class»
kWorkspaceBoss
ITextOptionsITextOptions
Session specific defaults that are
inherited by new documents.
Document specific defaults that are
inherited by new text frames.
Command used to change ITextOptions.
«boss class»
kSetFramePrefsCmdBoss
«boss class»
kCreateMultiColumnItemCmdBoss
Text Frame
Command used to create
new text frame. The defaults
can be overriden by passing
values in this command's
data interfaces..
IWorkspace IWorkspace
Text
Rendered Text
84
Sample Code
See the SnpManipulateTextPresentation::IncrementFrameColumns code snippet for an exam-
ple of using the ITextFrameOptionsSuite suite interface to manipulate default text-frame
options.
Manipulating Text Wrap
A page item can define a relationship with text. This relationship specifies what happens when
a text frame overlaps the page item, and it affects line-wrapping behavior. The behavior that
can be specified includes the following:
zWrapping text around the page item bounding box.
zWrapping text around the spline shape.
zFlowing text only where the frame and bounding box (or spline shape) of the page item
intersect.
You can prescribe the wrapping behavior a page item can enforce on text it overlaps.
Solution
Use HighLevelAPI::ITextWrapFacade to control text-wrapping behavior.
Sometimes, you may need to use lower-level API commands such as the following:
zkStandOffModeCmdBoss
zkStandOffFormCmdBoss
zkStandOffMarginCmdBoss
Sample Code
SnpManipulateTextFrame::ChangeTextWrapMode code snippet
Rendered Text
This section contains common use cases related to rendered text. The set of glyphs that make
up rendered text is called the wax.
Getting Notified of Composition Completion
You can when text is composed.
Solution
On completion of composition within a text frame, the message kRecomposeBoss is transmit-
ted along the IID_IFRAMECOMPOSER protocol to the frame item(kFrameItemBoss), spread
(kSpreadBoss), and document (kDocBoss). To be notified of composition completion, attach
Text 85
Text
Rendered Text
an observer to one of these objects. Which object you attach to depends on whether you want
to restrict the notifications to a single spread or page item.
Iterating the Wax for a Story
The SnpInspectTextModel::ReportWaxLineLeading SDK snippet iterates over each wax line
and reports the leading for all lines of text in a story.
You must keep your IWaxIterator in scope, to keep an IWaxLine interface pointer valid. The
following sample code demonstrates a common error caused when IWaxIterator is not kept in
scope:
static IWaxLine* QueryWaxLineContaining(
IWaxStrand* waxStrand, const TextIndex& textIndex)
{
IWaxLine* line = nil;
do{
K2::scoped_ptr<IWaxIterator> waxIterator =
waxIterator(waxStrand->NewWaxIterator());
if (waxIterator == nil)
break;
IWaxLine* waxLine = waxIterator->GetFirstWaxLine(textIndex);
if (waxLine == nil)
break;
line = waxLine;
line->AddRef();
// associated IWaxLine no longer valid when IWaxIterator is destructed.
} while(false);
return line; // Not a valid IWaxLine
}
To maintain references to several wax lines simultaneously, keep a wax iterator in scope for
each wax line. The sample code discussed in “Estimating the Composed Depth of Text in a
Frame or Parcel” on page 86 demonstrates this.
Creating Wax Lines and Wax Runs
Wax lines and wax runs are created by a paragraph composer. The SingleLineComposer SDK
sample is a paragraph composer that works on one line at a time. This sample demonstrate the
construction of wax lines and wax runs.
Text
Rendered Text
86
Finding the Wax displayed for a Range of Text
You can access the wax for a particular range of text.
Solution
The text must be fully composed. Follow these steps:
1. Navigate to the frame list boss (kFrameListBoss), in one of two ways. If dealing with a page
item, use IHierarchy::QueryChild, then IMultiColumnTextFrame ::QueryFrameList from
the multi-column boss object (kMultiColumnItemBoss). If dealing with a text story (kText-
StoryBoss), use ITextModel::QueryFrameList.
2. Obtain the wax strand (IWaxStrand) from the same boss object.
3. Use IWaxStrand::NewWaxIterator to get and iterator for the composed wax.
4. IWaxStrand::GetFirstWaxLine (IWaxStrand::GetNextWaxLine) returns a wax line (IWax-
Line on kWaxLineBoss).
Sample Code
SnpEstimateTextDepth code snippet
Estimating the Composed Depth of Text in a Frame or Parcel
You can estimate the depth of text in a text frame (kFrameItemBoss).
Solution
The text must be fully composed. Follow these steps:
1. Navigate to the frame list boss (kFrameListBoss), in one of two ways. if dealing with a page
item, use IHierarchy::QueryChild, then IMultiColumnTextFrame::QueryFrameList from
the multi-column boss object (kMultiColumnItemBoss). if dealing with a text story (kText-
StoryBoss), use ITextModel::QueryFrameList.
2. Obtain the wax strand (IWaxStrand) from the same boss object.
3. User IWaxStrand::NewWaxIterator to get an iterator for the composed wax. It takes an
index into the wax; determine the start character index and end character index for the
range of text you want to estimate. Create an iterator for each of these.
4. Use IWaxStrand::GetFirstWaxLine to get the wax line (IWaxLine on kWaxLineBoss) for
each iterator. You now have the wax line (IWaxLine) relating to the first and last lines in the
frame/parcel.
5. Use IWaxLine::GetYPosition to get the y position for the wax line. For horizontal text, the
depth of the text in a frame can be roughly estimated as the y position of the last line of wax
in the frame, minus the y position of the first line, plus the leading for the first line.
Text 87
Text
Text Composition
Sample Code
SnpEstimateTextDepth code snippet
Text Composition
The Need to Recompose Text in a Story
Normally, damaged text that requires recomposition is fixed by background composition. Your
code, however, may find the text in which it is interested is damaged; if so, it can force recom-
position to fix the damage. For example, always check for damage before scanning the wax or
relying on any spans that indicate the range of text stored in a frame or parcel.
Recomposing Text
You can recompose text within a story by either the index into the text model (TextIndex) or