nsMaiHyperlink.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsIURI.h"
  6. #include "nsMaiHyperlink.h"
  7. #include "mozilla/a11y/ProxyAccessible.h"
  8. using namespace mozilla::a11y;
  9. /* MaiAtkHyperlink */
  10. #define MAI_TYPE_ATK_HYPERLINK (mai_atk_hyperlink_get_type ())
  11. #define MAI_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
  12. MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
  13. #define MAI_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
  14. MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
  15. #define MAI_IS_ATK_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
  16. MAI_TYPE_ATK_HYPERLINK))
  17. #define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
  18. MAI_TYPE_ATK_HYPERLINK))
  19. #define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
  20. MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
  21. /**
  22. * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace,
  23. * for AtkHyperlink
  24. */
  25. struct MaiAtkHyperlink
  26. {
  27. AtkHyperlink parent;
  28. /*
  29. * The MaiHyperlink whose properties and features are exported via this
  30. * hyperlink instance.
  31. */
  32. MaiHyperlink *maiHyperlink;
  33. };
  34. struct MaiAtkHyperlinkClass
  35. {
  36. AtkHyperlinkClass parent_class;
  37. };
  38. GType mai_atk_hyperlink_get_type(void);
  39. G_BEGIN_DECLS
  40. /* callbacks for AtkHyperlink */
  41. static void classInitCB(AtkHyperlinkClass *aClass);
  42. static void finalizeCB(GObject *aObj);
  43. /* callbacks for AtkHyperlink virtual functions */
  44. static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex);
  45. static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
  46. static gint getEndIndexCB(AtkHyperlink *aLink);
  47. static gint getStartIndexCB(AtkHyperlink *aLink);
  48. static gboolean isValidCB(AtkHyperlink *aLink);
  49. static gint getAnchorCountCB(AtkHyperlink *aLink);
  50. G_END_DECLS
  51. static gpointer parent_class = nullptr;
  52. static MaiHyperlink*
  53. GetMaiHyperlink(AtkHyperlink *aHyperlink)
  54. {
  55. NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
  56. MaiHyperlink * maiHyperlink =
  57. MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
  58. NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
  59. NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
  60. return maiHyperlink;
  61. }
  62. GType
  63. mai_atk_hyperlink_get_type(void)
  64. {
  65. static GType type = 0;
  66. if (!type) {
  67. static const GTypeInfo tinfo = {
  68. sizeof(MaiAtkHyperlinkClass),
  69. (GBaseInitFunc)nullptr,
  70. (GBaseFinalizeFunc)nullptr,
  71. (GClassInitFunc)classInitCB,
  72. (GClassFinalizeFunc)nullptr,
  73. nullptr, /* class data */
  74. sizeof(MaiAtkHyperlink), /* instance size */
  75. 0, /* nb preallocs */
  76. (GInstanceInitFunc)nullptr,
  77. nullptr /* value table */
  78. };
  79. type = g_type_register_static(ATK_TYPE_HYPERLINK,
  80. "MaiAtkHyperlink",
  81. &tinfo, GTypeFlags(0));
  82. }
  83. return type;
  84. }
  85. MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) :
  86. mHyperlink(aHyperLink),
  87. mMaiAtkHyperlink(nullptr)
  88. {
  89. mMaiAtkHyperlink =
  90. reinterpret_cast<AtkHyperlink *>
  91. (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
  92. NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
  93. if (!mMaiAtkHyperlink)
  94. return;
  95. MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
  96. }
  97. MaiHyperlink::~MaiHyperlink()
  98. {
  99. if (mMaiAtkHyperlink) {
  100. MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
  101. g_object_unref(mMaiAtkHyperlink);
  102. }
  103. }
  104. /* static functions for ATK callbacks */
  105. void
  106. classInitCB(AtkHyperlinkClass *aClass)
  107. {
  108. GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
  109. parent_class = g_type_class_peek_parent(aClass);
  110. aClass->get_uri = getUriCB;
  111. aClass->get_object = getObjectCB;
  112. aClass->get_end_index = getEndIndexCB;
  113. aClass->get_start_index = getStartIndexCB;
  114. aClass->is_valid = isValidCB;
  115. aClass->get_n_anchors = getAnchorCountCB;
  116. gobject_class->finalize = finalizeCB;
  117. }
  118. void
  119. finalizeCB(GObject *aObj)
  120. {
  121. NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
  122. if (!MAI_IS_ATK_HYPERLINK(aObj))
  123. return;
  124. MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
  125. maiAtkHyperlink->maiHyperlink = nullptr;
  126. /* call parent finalize function */
  127. if (G_OBJECT_CLASS (parent_class)->finalize)
  128. G_OBJECT_CLASS (parent_class)->finalize(aObj);
  129. }
  130. gchar *
  131. getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
  132. {
  133. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  134. if (!maiLink)
  135. return nullptr;
  136. nsAutoCString cautoStr;
  137. if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
  138. nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
  139. if (!uri)
  140. return nullptr;
  141. nsresult rv = uri->GetSpec(cautoStr);
  142. NS_ENSURE_SUCCESS(rv, nullptr);
  143. return g_strdup(cautoStr.get());
  144. }
  145. bool valid;
  146. maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
  147. if (!valid)
  148. return nullptr;
  149. return g_strdup(cautoStr.get());
  150. }
  151. AtkObject *
  152. getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
  153. {
  154. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  155. if (!maiLink) {
  156. return nullptr;
  157. }
  158. if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
  159. Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
  160. NS_ENSURE_TRUE(anchor, nullptr);
  161. return AccessibleWrap::GetAtkObject(anchor);
  162. }
  163. ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
  164. return anchor ? GetWrapperFor(anchor) : nullptr;
  165. }
  166. gint
  167. getEndIndexCB(AtkHyperlink *aLink)
  168. {
  169. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  170. if (!maiLink)
  171. return false;
  172. if (Accessible* hyperlink = maiLink->GetAccHyperlink())
  173. return static_cast<gint>(hyperlink->EndOffset());
  174. bool valid = false;
  175. uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
  176. return valid ? static_cast<gint>(endIdx) : -1;
  177. }
  178. gint
  179. getStartIndexCB(AtkHyperlink *aLink)
  180. {
  181. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  182. if (!maiLink)
  183. return -1;
  184. if (Accessible* hyperlink = maiLink->GetAccHyperlink())
  185. return static_cast<gint>(hyperlink->StartOffset());
  186. bool valid = false;
  187. uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
  188. return valid ? static_cast<gint>(startIdx) : -1;
  189. }
  190. gboolean
  191. isValidCB(AtkHyperlink *aLink)
  192. {
  193. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  194. if (!maiLink)
  195. return false;
  196. if (Accessible* hyperlink = maiLink->GetAccHyperlink())
  197. return static_cast<gboolean>(hyperlink->IsLinkValid());
  198. return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
  199. }
  200. gint
  201. getAnchorCountCB(AtkHyperlink *aLink)
  202. {
  203. MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
  204. if (!maiLink)
  205. return -1;
  206. if (Accessible* hyperlink = maiLink->GetAccHyperlink())
  207. return static_cast<gint>(hyperlink->AnchorCount());
  208. bool valid = false;
  209. uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
  210. return valid ? static_cast<gint>(anchorCount) : -1;
  211. }