1
/*
2
 * Copyright 2008 Codethink Ltd.
3
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the
17
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
 * Boston, MA 02110-1301, USA.
19
 */
20

            
21
#include <atk/atk.h>
22
#include <glib.h>
23
#include <stdio.h>
24
#include <string.h>
25

            
26
#include "my-atk-hyperlink.h"
27
#include "my-atk-hypertext.h"
28
#include "my-atk-object.h"
29

            
30
typedef struct _MyAtkHypertextInfo MyAtkHypertextInfo;
31

            
32
static void atk_hypertext_interface_init (AtkHypertextIface *iface);
33
static void GDestroyNotifyGOBJptrArray (gpointer data);
34

            
35
10
G_DEFINE_TYPE_WITH_CODE (MyAtkHypertext,
36
                         my_atk_hypertext,
37
                         MY_TYPE_ATK_OBJECT,
38
                         G_IMPLEMENT_INTERFACE (ATK_TYPE_HYPERTEXT,
39
                                                atk_hypertext_interface_init));
40

            
41
gint
42
10
my_atk_set_hypertext (AtkHypertext *obj, const gchar *text)
43
{
44
10
  MyAtkHypertext *self = MY_ATK_HYPERTEXT (obj);
45
  MyAtkHyperlink *link;
46
  gchar *ptr;
47
10
  const gchar *fstr = "href=";
48
10
  gint len = strlen (fstr);
49
10
  gint text_len = strlen (text);
50
10
  gint index = 0;
51
  gint start_offset;
52
10
  g_return_val_if_fail (MY_IS_ATK_HYPERTEXT (obj), -1);
53

            
54
10
  if (text_len < len)
55
    return -1;
56

            
57
40
  while (text)
58
    {
59
30
      ptr = g_strstr_len (text + index, text_len - index, fstr);
60
30
      index = ptr - text + len;
61
30
      if (ptr)
62
        {
63
20
          if (text_len < index || index < len)
64
            break;
65
20
          if (text[index] == '\'')
66
            {
67
20
              start_offset = index + 1;
68
250
              while (++index < text_len && text[index] != '\'')
69
                ;
70
20
              if (text[index] != '\'')
71
                break;
72
20
              link = new_MyAtkHyperlink ();
73
20
              my_atk_set_hyperlink (ATK_HYPERLINK (link),
74
20
                                    g_strndup (text + start_offset, index - start_offset),
75
                                    start_offset,
76
                                    index);
77
20
              g_ptr_array_add (self->array, link);
78
            }
79
        }
80
      else
81
10
        break;
82
    }
83

            
84
10
  return self->array->len > 0 ? 0 : -1;
85
}
86

            
87
static gint
88
1
my_atk_hypertext_get_n_links (AtkHypertext *obj)
89
{
90
1
  MyAtkHypertext *self = MY_ATK_HYPERTEXT (obj);
91
1
  g_return_val_if_fail (MY_IS_ATK_HYPERTEXT (obj), -1);
92
1
  return self->array->len;
93
}
94

            
95
static AtkHyperlink *
96
9
my_atk_hypertext_get_link (AtkHypertext *obj, gint link_index)
97
{
98
9
  MyAtkHypertext *self = MY_ATK_HYPERTEXT (obj);
99
9
  AtkHyperlink *link = NULL;
100
9
  g_return_val_if_fail (MY_IS_ATK_HYPERTEXT (obj), NULL);
101
9
  if (0 <= link_index && link_index < self->array->len)
102
9
    link = g_ptr_array_index (self->array, link_index);
103
9
  return link;
104
}
105

            
106
static gint
107
3
my_atk_hypertext_get_link_index (AtkHypertext *obj, gint char_index)
108
{
109
3
  MyAtkHypertext *self = MY_ATK_HYPERTEXT (obj);
110
  gint i;
111
  MyAtkHyperlink *link;
112
3
  g_return_val_if_fail (MY_IS_ATK_HYPERTEXT (obj), -1);
113

            
114
6
  for (i = 0; i < self->array->len; i++)
115
    {
116
5
      link = g_ptr_array_index (self->array, i);
117
5
      if (link->start <= char_index && char_index <= link->end)
118
2
        return i;
119
    }
120
1
  return -1;
121
}
122

            
123
static void
124
my_atk_hypertext_link_selected (AtkHypertext *obj, gint link_index)
125
{
126
  g_return_if_fail (MY_IS_ATK_HYPERTEXT (obj));
127
}
128

            
129
static void
130
GDestroyNotifyGOBJptrArray (gpointer data)
131
{
132
  g_object_unref (data);
133
}
134

            
135
static void
136
10
atk_hypertext_interface_init (AtkHypertextIface *iface)
137
{
138
10
  if (!iface)
139
    return;
140
10
  iface->get_n_links = my_atk_hypertext_get_n_links;
141
10
  iface->get_link = my_atk_hypertext_get_link;
142
10
  iface->get_link_index = my_atk_hypertext_get_link_index;
143
10
  iface->link_selected = my_atk_hypertext_link_selected;
144
}
145

            
146
static void
147
10
my_atk_hypertext_init (MyAtkHypertext *self)
148
{
149
10
  self->array = g_ptr_array_new_full (2, GDestroyNotifyGOBJptrArray);
150
10
}
151

            
152
static void
153
my_atk_hypertext_class_initialize (AtkObject *obj, gpointer data)
154
{
155
}
156

            
157
static void
158
my_atk_hypertext_class_finalize (GObject *obj)
159
{
160
}
161

            
162
static void
163
10
my_atk_hypertext_class_init (MyAtkHypertextClass *my_class)
164
{
165
10
  AtkObjectClass *atk_class = ATK_OBJECT_CLASS (my_class);
166
10
  GObjectClass *gobject_class = G_OBJECT_CLASS (my_class);
167

            
168
10
  gobject_class->finalize = my_atk_hypertext_class_finalize;
169

            
170
10
  atk_class->initialize = my_atk_hypertext_class_initialize;
171
10
}