1
/* ATK -  Accessibility Toolkit
2
 * Copyright 2001 Sun Microsystems Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 * Boston, MA 02111-1307, USA.
18
 */
19

            
20
#include "config.h"
21

            
22
#include "atkdocument.h"
23
#include "atkmarshal.h"
24

            
25
/**
26
 * AtkDocument:
27
 *
28
 * The ATK interface which represents the toplevel
29
 *  container for document content.
30
 *
31
 * The AtkDocument interface should be supported by any object whose
32
 * content is a representation or view of a document.  The AtkDocument
33
 * interface should appear on the toplevel container for the document
34
 * content; however AtkDocument instances may be nested (i.e. an
35
 * AtkDocument may be a descendant of another AtkDocument) in those
36
 * cases where one document contains "embedded content" which can
37
 * reasonably be considered a document in its own right.
38
 *
39
 */
40

            
41
enum
42
{
43
  LOAD_COMPLETE,
44
  RELOAD,
45
  LOAD_STOPPED,
46
  PAGE_CHANGED,
47
  DOCUMENT_ATTRIBUTE_CHANGED,
48
  LAST_SIGNAL
49
};
50

            
51
static void atk_document_base_init (AtkDocumentIface *class);
52

            
53
static guint atk_document_signals[LAST_SIGNAL] = { 0 };
54

            
55
GType
56
2544
atk_document_get_type (void)
57
{
58
  static GType type = 0;
59

            
60
2544
  if (!type)
61
    {
62
      static const GTypeInfo tinfo = {
63
        sizeof (AtkDocumentIface),
64
        (GBaseInitFunc) atk_document_base_init,
65
        (GBaseFinalizeFunc) NULL,
66

            
67
      };
68

            
69
162
      type = g_type_register_static (G_TYPE_INTERFACE, "AtkDocument", &tinfo, 0);
70
    }
71

            
72
2544
  return type;
73
}
74

            
75
static void
76
329
atk_document_base_init (AtkDocumentIface *class)
77
{
78
  static gboolean initialized = FALSE;
79
329
  if (!initialized)
80
    {
81
      /**
82
       * AtkDocument::load-complete:
83
       * @atkdocument: the object which received the signal.
84
       *
85
       * The 'load-complete' signal is emitted when a pending load of
86
       * a static document has completed.  This signal is to be
87
       * expected by ATK clients if and when AtkDocument implementors
88
       * expose ATK_STATE_BUSY.  If the state of an AtkObject which
89
       * implements AtkDocument does not include ATK_STATE_BUSY, it
90
       * should be safe for clients to assume that the AtkDocument's
91
       * static contents are fully loaded into the container.
92
       * (Dynamic document contents should be exposed via other
93
       * signals.)
94
       */
95
162
      atk_document_signals[LOAD_COMPLETE] =
96
162
          g_signal_new ("load_complete",
97
                        ATK_TYPE_DOCUMENT,
98
                        G_SIGNAL_RUN_LAST,
99
                        0,
100
                        (GSignalAccumulator) NULL, NULL,
101
                        g_cclosure_marshal_VOID__VOID,
102
                        G_TYPE_NONE, 0);
103
      /**
104
       * AtkDocument::reload:
105
       * @atkdocument: the object which received the signal.
106
       *
107
       * The 'reload' signal is emitted when the contents of a
108
       * document is refreshed from its source.  Once 'reload' has
109
       * been emitted, a matching 'load-complete' or 'load-stopped'
110
       * signal should follow, which clients may await before
111
       * interrogating ATK for the latest document content.
112
       */
113
162
      atk_document_signals[RELOAD] =
114
162
          g_signal_new ("reload",
115
                        ATK_TYPE_DOCUMENT,
116
                        G_SIGNAL_RUN_LAST,
117
                        0,
118
                        (GSignalAccumulator) NULL, NULL,
119
                        g_cclosure_marshal_VOID__VOID,
120
                        G_TYPE_NONE, 0);
121

            
122
      /**
123
       * AtkDocument::load-stopped:
124
       * @atkdocument: the object which received the signal.
125
       *
126
       * The 'load-stopped' signal is emitted when a pending load of
127
       * document contents is cancelled, paused, or otherwise
128
       * interrupted by the user or application logic.  It should not
129
       * however be emitted while waiting for a resource (for instance
130
       * while blocking on a file or network read) unless a
131
       * user-significant timeout has occurred.
132
       */
133
162
      atk_document_signals[LOAD_STOPPED] =
134
162
          g_signal_new ("load_stopped",
135
                        ATK_TYPE_DOCUMENT,
136
                        G_SIGNAL_RUN_LAST,
137
                        0,
138
                        (GSignalAccumulator) NULL, NULL,
139
                        g_cclosure_marshal_VOID__VOID,
140
                        G_TYPE_NONE, 0);
141

            
142
      /**
143
       * AtkDocument::page-changed:
144
       * @atkdocument: the object on which the signal was emitted
145
       * @page_number: the new page number. If this value is unknown
146
       * or not applicable, -1 should be provided.
147
       *
148
       * The 'page-changed' signal is emitted when the current page of
149
       * a document changes, e.g. pressing page up/down in a document
150
       * viewer.
151
       *
152
       * Since: 2.12
153
       */
154
162
      atk_document_signals[PAGE_CHANGED] =
155
162
          g_signal_new ("page_changed",
156
                        ATK_TYPE_DOCUMENT,
157
                        G_SIGNAL_RUN_LAST,
158
                        0,
159
                        (GSignalAccumulator) NULL, NULL,
160
                        g_cclosure_marshal_VOID__INT,
161
                        G_TYPE_NONE, 1, G_TYPE_INT);
162

            
163
      /**
164
       * AtkDocument::document-attribute-changed
165
       * @atkdocument: the object which received the signal.
166
       * @arg1: the name of the attribute being modified, or %NULL if not
167
       *          available.
168
       * @arg2: the attribute's new value, or %null if not available.
169
       *
170
       * The "document-attribute-changed" signal should be emitted when there is a
171
       * change to one of the document attributes returned by
172
       * atk_document_get_attributes.
173
       *
174
       * Since: 2.52
175
       */
176
162
      atk_document_signals[DOCUMENT_ATTRIBUTE_CHANGED] =
177
162
          g_signal_new ("document-attribute-changed",
178
                        ATK_TYPE_DOCUMENT,
179
                        G_SIGNAL_RUN_LAST,
180
                        0,
181
                        NULL, NULL,
182
                        atk_marshal_VOID__STRING_STRING,
183
                        G_TYPE_NONE,
184
                        2, G_TYPE_STRING, G_TYPE_STRING);
185
162
      initialized = TRUE;
186
    }
187
329
}
188

            
189
/**
190
 * atk_document_get_document_type: (virtual get_document_type)
191
 * @document: a #GObject instance that implements AtkDocumentIface
192
 *
193
 * Gets a string indicating the document type.
194
 *
195
 * Deprecated: Since 2.12. Please use atk_document_get_attributes() to
196
 * ask for the document type if it applies.
197
 *
198
 * Returns: a string indicating the document type
199
 **/
200
const gchar *
201
atk_document_get_document_type (AtkDocument *document)
202
{
203
  AtkDocumentIface *iface;
204

            
205
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
206

            
207
  iface = ATK_DOCUMENT_GET_IFACE (document);
208

            
209
  if (iface->get_document_type)
210
    {
211
      return (iface->get_document_type) (document);
212
    }
213
  else
214
    {
215
      return NULL;
216
    }
217
}
218

            
219
/**
220
 * atk_document_get_document: (virtual get_document)
221
 * @document: a #GObject instance that implements AtkDocumentIface
222
 *
223
 * Gets a %gpointer that points to an instance of the DOM.  It is
224
 * up to the caller to check atk_document_get_type to determine
225
 * how to cast this pointer.
226
 *
227
 * Deprecated: Since 2.12. @document is already a representation of
228
 * the document. Use it directly, or one of its children, as an
229
 * instance of the DOM.
230
 *
231
 * Returns: (transfer none): a %gpointer that points to an instance of the DOM.
232
 **/
233
gpointer
234
atk_document_get_document (AtkDocument *document)
235
{
236
  AtkDocumentIface *iface;
237

            
238
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
239

            
240
  iface = ATK_DOCUMENT_GET_IFACE (document);
241

            
242
  if (iface->get_document)
243
    {
244
      return (iface->get_document) (document);
245
    }
246
  else
247
    {
248
      return NULL;
249
    }
250
}
251

            
252
/**
253
 * atk_document_get_locale: (virtual get_document_locale)
254
 * @document: a #GObject instance that implements AtkDocumentIface
255
 *
256
 * Gets a UTF-8 string indicating the POSIX-style LC_MESSAGES locale
257
 *          of the content of this document instance.  Individual
258
 *          text substrings or images within this document may have
259
 *          a different locale, see atk_text_get_attributes and
260
 *          atk_image_get_image_locale.
261
 *
262
 * Deprecated: 2.7.90: Please use atk_object_get_object_locale() instead.
263
 *
264
 * Returns: a UTF-8 string indicating the POSIX-style LC_MESSAGES
265
 *          locale of the document content as a whole, or NULL if
266
 *          the document content does not specify a locale.
267
 **/
268
const gchar *
269
1
atk_document_get_locale (AtkDocument *document)
270
{
271
  AtkDocumentIface *iface;
272

            
273
1
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
274

            
275
1
  iface = ATK_DOCUMENT_GET_IFACE (document);
276

            
277
1
  if (iface->get_document_locale)
278
    {
279
1
      return (iface->get_document_locale) (document);
280
    }
281
  else
282
    {
283
      return NULL;
284
    }
285
}
286

            
287
/**
288
 * atk_document_get_attributes: (virtual get_document_attributes)
289
 * @document: a #GObject instance that implements AtkDocumentIface
290
 *
291
 * Gets an AtkAttributeSet which describes document-wide
292
 *          attributes as name-value pairs.
293
 *
294
 * Since: 1.12
295
 *
296
 * Returns: (transfer none): An AtkAttributeSet containing the explicitly
297
 *          set name-value-pair attributes associated with this document
298
 *          as a whole.
299
 **/
300
AtkAttributeSet *
301
1
atk_document_get_attributes (AtkDocument *document)
302
{
303
  AtkDocumentIface *iface;
304

            
305
1
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
306

            
307
1
  iface = ATK_DOCUMENT_GET_IFACE (document);
308

            
309
1
  if (iface->get_document_attributes)
310
    {
311
1
      return (iface->get_document_attributes) (document);
312
    }
313
  else
314
    {
315
      return NULL;
316
    }
317
}
318

            
319
/**
320
 * atk_document_get_attribute_value: (virtual get_document_attribute_value)
321
 * @document: a #GObject instance that implements AtkDocumentIface
322
 * @attribute_name: a character string representing the name of the attribute
323
 *   whose value is being queried.
324
 *
325
 * Retrieves the value of the given @attribute_name inside @document.
326
 *
327
 * Returns: (nullable): a string value associated with the named
328
 *    attribute for this document, or %NULL if a value for
329
 *    @attribute_name has not been specified for this document.
330
 *
331
 * Since: 1.12
332
 */
333
const gchar *
334
2
atk_document_get_attribute_value (AtkDocument *document,
335
                                  const gchar *attribute_name)
336
{
337
  AtkDocumentIface *iface;
338

            
339
2
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
340

            
341
2
  iface = ATK_DOCUMENT_GET_IFACE (document);
342

            
343
2
  if (iface->get_document_attribute_value)
344
    {
345
2
      return (iface->get_document_attribute_value) (document, attribute_name);
346
    }
347
  else
348
    {
349
      return NULL;
350
    }
351
}
352

            
353
/**
354
 * atk_document_set_attribute_value: (virtual set_document_attribute)
355
 * @document: a #GObject instance that implements #AtkDocumentIface
356
 * @attribute_name: a character string representing the name of the attribute
357
 *   whose value is being set.
358
 * @attribute_value: a string value to be associated with @attribute_name.
359
 *
360
 * Sets the value for the given @attribute_name inside @document.
361
 *
362
 * Since: 1.12
363
 *
364
 * Returns: %TRUE if @attribute_value is successfully associated
365
 *   with @attribute_name for this @document, and %FALSE if if the
366
 *   document does not allow the attribute to be modified
367
 */
368
gboolean
369
atk_document_set_attribute_value (AtkDocument *document,
370
                                  const gchar *attribute_name,
371
                                  const gchar *attribute_value)
372
{
373
  AtkDocumentIface *iface;
374

            
375
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), FALSE);
376

            
377
  iface = ATK_DOCUMENT_GET_IFACE (document);
378

            
379
  if (iface->set_document_attribute)
380
    {
381
      return (iface->set_document_attribute) (document, attribute_name, attribute_value);
382
    }
383
  else
384
    {
385
      return FALSE;
386
    }
387
}
388

            
389
/**
390
 * atk_document_get_current_page_number:
391
 * @document: the #AtkDocument
392
 *
393
 * Retrieves the current page number inside @document.
394
 *
395
 * Returns: the current page number inside @document, or -1 if
396
 *   not implemented, not know by the implementor, or irrelevant.
397
 *
398
 * Since: 2.12
399
 */
400
gint
401
atk_document_get_current_page_number (AtkDocument *document)
402
{
403
  AtkDocumentIface *iface;
404

            
405
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), FALSE);
406

            
407
  iface = ATK_DOCUMENT_GET_IFACE (document);
408

            
409
  if (iface->get_current_page_number)
410
    {
411
      return (iface->get_current_page_number) (document);
412
    }
413
  else
414
    {
415
      return -1;
416
    }
417
}
418

            
419
/**
420
 * atk_document_get_page_count:
421
 * @document: the #AtkDocument
422
 *
423
 * Retrieves the total number of pages inside @document.
424
 *
425
 * Returns: total page count of @document, or -1 if not implemented,
426
 *   not know by the implementor or irrelevant.
427
 *
428
 * Since: 2.12
429
 */
430
gint
431
atk_document_get_page_count (AtkDocument *document)
432
{
433
  AtkDocumentIface *iface;
434

            
435
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), FALSE);
436

            
437
  iface = ATK_DOCUMENT_GET_IFACE (document);
438

            
439
  if (iface->get_page_count)
440
    {
441
      return (iface->get_page_count) (document);
442
    }
443
  else
444
    {
445
      return -1;
446
    }
447
}
448

            
449
/**
450
 * atk_document_get_text_selections:
451
 * @document: an #AtkDocument
452
 *
453
 * Returns an array of AtkTextSelections within this document.
454
 *
455
 * Returns: (element-type AtkTextSelection) (transfer full): a GArray of
456
 * AtkTextSelection structures representing the selection.
457
 *
458
 * Since: 2.52
459
 */
460
GArray *
461
2
atk_document_get_text_selections (AtkDocument *document)
462
{
463
  AtkDocumentIface *iface;
464

            
465
2
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), NULL);
466

            
467
2
  iface = ATK_DOCUMENT_GET_IFACE (document);
468

            
469
2
  if (iface->get_text_selections)
470
2
    return (*(iface->get_text_selections)) (document);
471
  else
472
    return NULL;
473
}
474

            
475
/**
476
 * atk_document_set_text_selections:
477
 * @document: an #AtkDocument.
478
 * @selections: (element-type AtkTextSelection): a GArray of AtkTextSelections
479
 *              to be selected.
480
 *
481
 * Makes 1 or more selections within this document denoted by the given
482
 * array of AtkTextSelections. Any existing physical selection (inside or
483
 * outside this document) is replaced by the new selections. All objects within
484
 * the given selection ranges must be descendants of this document. Otherwise
485
 * FALSE will be returned.
486
 *
487
 * Returns: TRUE if the selection was made successfully; FALSE otherwise.
488
 *
489
 * Since: 2.52
490
 */
491
gboolean
492
1
atk_document_set_text_selections (AtkDocument *document,
493
                                  GArray *selections)
494
{
495
  AtkDocumentIface *iface;
496

            
497
1
  g_return_val_if_fail (ATK_IS_DOCUMENT (document), FALSE);
498

            
499
1
  iface = ATK_DOCUMENT_GET_IFACE (document);
500

            
501
1
  if (iface->set_text_selections)
502
1
    return (*(iface->set_text_selections)) (document, selections);
503
  else
504
    return FALSE;
505
}