LibreOffice Module cui (master)  1
cuicharmap.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <stdio.h>
21 
22 #include <vcl/svapp.hxx>
23 #include <svl/eitem.hxx>
24 #include <svl/intitem.hxx>
25 #include <svl/itempool.hxx>
26 
27 #include <rtl/textenc.h>
28 #include <svx/ucsubset.hxx>
29 #include <vcl/settings.hxx>
30 #include <vcl/fontcharmap.hxx>
31 #include <vcl/virdev.hxx>
32 #include <svl/stritem.hxx>
33 #include <o3tl/temporary.hxx>
34 #include <officecfg/Office/Common.hxx>
35 #include <com/sun/star/beans/PropertyValue.hpp>
38 
39 #include <dialmgr.hxx>
40 #include <cui/cuicharmap.hxx>
41 #include <sfx2/app.hxx>
42 #include <svx/svxids.hrc>
43 #include <editeng/editids.hrc>
44 #include <editeng/fontitem.hxx>
45 #include <strings.hrc>
46 #include <unicode/uchar.h>
47 #include <unicode/utypes.h>
48 
49 using namespace css;
50 
52  const css::uno::Reference<css::frame::XFrame>& rFrame)
53  : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog")
54  , m_xVirDev(VclPtr<VirtualDevice>::Create())
55  , isSearchMode(true)
56  , m_xFrame(rFrame)
58  , m_aRecentCharView{SvxCharView(m_xVirDev),
74  , m_aFavCharView{SvxCharView(m_xVirDev),
75  SvxCharView(m_xVirDev),
76  SvxCharView(m_xVirDev),
77  SvxCharView(m_xVirDev),
78  SvxCharView(m_xVirDev),
79  SvxCharView(m_xVirDev),
80  SvxCharView(m_xVirDev),
81  SvxCharView(m_xVirDev),
82  SvxCharView(m_xVirDev),
83  SvxCharView(m_xVirDev),
84  SvxCharView(m_xVirDev),
85  SvxCharView(m_xVirDev),
86  SvxCharView(m_xVirDev),
87  SvxCharView(m_xVirDev),
88  SvxCharView(m_xVirDev),
89  SvxCharView(m_xVirDev)}
90  , m_aShowChar(m_xVirDev)
91  , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok"))
92  , m_xFontText(m_xBuilder->weld_label("fontft"))
93  , m_xFontLB(m_xBuilder->weld_combo_box("fontlb"))
94  , m_xSubsetText(m_xBuilder->weld_label("subsetft"))
95  , m_xSubsetLB(m_xBuilder->weld_combo_box("subsetlb"))
96  , m_xSearchText(m_xBuilder->weld_entry("search"))
97  , m_xHexCodeText(m_xBuilder->weld_entry("hexvalue"))
98  , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue"))
99  , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn"))
100  , m_xCharName(m_xBuilder->weld_label("charname"))
101  , m_xRecentGrid(m_xBuilder->weld_widget("viewgrid"))
102  , m_xFavGrid(m_xBuilder->weld_widget("favgrid"))
103  , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar))
104  , m_xRecentCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar1", m_aRecentCharView[0]),
105  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar2", m_aRecentCharView[1]),
106  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar3", m_aRecentCharView[2]),
107  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar4", m_aRecentCharView[3]),
108  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar5", m_aRecentCharView[4]),
109  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar6", m_aRecentCharView[5]),
110  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar7", m_aRecentCharView[6]),
111  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar8", m_aRecentCharView[7]),
112  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar9", m_aRecentCharView[8]),
113  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar10", m_aRecentCharView[9]),
114  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar11", m_aRecentCharView[10]),
115  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar12", m_aRecentCharView[11]),
116  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar13", m_aRecentCharView[12]),
117  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar14", m_aRecentCharView[13]),
118  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar15", m_aRecentCharView[14]),
119  std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar16", m_aRecentCharView[15])}
120  , m_xFavCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar1", m_aFavCharView[0]),
121  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar2", m_aFavCharView[1]),
122  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar3", m_aFavCharView[2]),
123  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar4", m_aFavCharView[3]),
124  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar5", m_aFavCharView[4]),
125  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar6", m_aFavCharView[5]),
126  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar7", m_aFavCharView[6]),
127  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar8", m_aFavCharView[7]),
128  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar9", m_aFavCharView[8]),
129  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar10", m_aFavCharView[9]),
130  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar11", m_aFavCharView[10]),
131  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar12", m_aFavCharView[11]),
132  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar13", m_aFavCharView[12]),
133  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar14", m_aFavCharView[13]),
134  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar15", m_aFavCharView[14]),
135  std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar16", m_aFavCharView[15])}
136  , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll", true), m_xVirDev))
137  , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
138  , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll", true), m_xVirDev))
139  , m_xSearchSetArea(new weld::CustomWeld(*m_xBuilder, "searchcharset", *m_xSearchSet))
140 {
141  m_aShowChar.SetCentered(true);
142  m_xFontLB->make_sorted();
143  //lock the size request of this widget to the width of all possible entries
144  fillAllSubsets(*m_xSubsetLB);
145  m_xSubsetLB->set_size_request(m_xSubsetLB->get_preferred_size().Width(), -1);
146  m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4);
147  //lock the size request of this widget to the width of the original .ui string
148  m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1);
149  //so things don't jump around if all the children are hidden
150  m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
151  m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());
152 
153  init();
154 
155  const SfxInt32Item* pCharItem = SfxItemSet::GetItem<SfxInt32Item>(pSet, SID_ATTR_CHAR, false);
156  if ( pCharItem )
157  SetChar( pCharItem->GetValue() );
158 
159  const SfxBoolItem* pDisableItem = SfxItemSet::GetItem<SfxBoolItem>(pSet, FN_PARAM_2, false);
160  if ( pDisableItem && pDisableItem->GetValue() )
161  DisableFontSelection();
162 
163  const SvxFontItem* pFontItem = SfxItemSet::GetItem<SvxFontItem>(pSet, SID_ATTR_CHAR_FONT, false);
164  const SfxStringItem* pFontNameItem = SfxItemSet::GetItem<SfxStringItem>(pSet, SID_FONT_NAME, false);
165  if ( pFontItem )
166  {
167  vcl::Font aTmpFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetFontSize() );
168  aTmpFont.SetCharSet( pFontItem->GetCharSet() );
169  aTmpFont.SetPitch( pFontItem->GetPitch() );
170  SetCharFont( aTmpFont );
171  }
172  else if ( pFontNameItem )
173  {
174  vcl::Font aTmpFont( GetCharFont() );
175  aTmpFont.SetFamilyName( pFontNameItem->GetValue() );
176  SetCharFont( aTmpFont );
177  }
178 
179  m_xOutputSet.reset(new SfxAllItemSet(pSet ? *pSet->GetPool() : SfxGetpApp()->GetPool()));
180  m_xShowSet->Show();
181  m_xSearchSet->Hide();
182 }
183 
185 {
186  if( SvxShowCharSet::getSelectedChar() == ' ')
187  {
188  m_xOKBtn->set_sensitive(false);
189  setFavButtonState(u"", u"");
190  }
191  else
192  {
193  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
194  // using the new UCS4 constructor
195  OUString aOUStr( &cChar, 1 );
196  m_aShowChar.SetText(aOUStr);
197 
199  m_xOKBtn->set_sensitive(true);
200  }
201 
202  return SfxDialogController::run();
203 }
204 
206 {
207  m_xShowSet->SelectCharacter( c );
208  setFavButtonState(OUString(&c, 1), aFont.GetFamilyName());
209 }
210 
212 {
213  return m_aShowChar.GetText().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
214 }
215 
217 {
218  m_xFontText->set_sensitive(false);
219  m_xFontLB->set_sensitive(false);
220 }
221 
222 
224 {
225  //retrieve recent character list
226  const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
227  for (OUString const & s : rRecentCharList)
228  {
229  maRecentCharList.push_back(s);
230  }
231 
232  //retrieve recent character font list
233  const css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
234  for (OUString const & s : rRecentCharFontList)
235  {
236  maRecentCharFontList.push_back(s);
237  }
238 
239  // tdf#135997: make sure that the two lists are same length
240  const auto nCommonLength = std::min(maRecentCharList.size(), maRecentCharFontList.size());
241  maRecentCharList.resize(nCommonLength);
242  maRecentCharFontList.resize(nCommonLength);
243 }
244 
245 
247 {
248  maFavCharList.clear();
249  maFavCharFontList.clear();
250  //retrieve recent character list
251  const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
252  for (const OUString& s : rFavCharList)
253  {
254  maFavCharList.push_back(s);
255  }
256 
257  //retrieve recent character font list
258  const css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
259  for (const OUString& s : rFavCharFontList)
260  {
261  maFavCharFontList.push_back(s);
262  }
263 
264  // tdf#135997: make sure that the two lists are same length
265  const auto nCommonLength = std::min(maFavCharList.size(), maFavCharFontList.size());
266  maFavCharList.resize(nCommonLength);
267  maFavCharFontList.resize(nCommonLength);
268 }
269 
270 static std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
271 findInPair(std::u16string_view str1, const std::deque<OUString>& rContainer1,
272  std::u16string_view str2, const std::deque<OUString>& rContainer2)
273 {
274  assert(rContainer1.size() == rContainer2.size());
275 
276  if (auto it1 = std::find(rContainer1.begin(), rContainer1.end(), str1);
277  it1 != rContainer1.end())
278  {
279  auto it2 = rContainer2.begin() + (it1 - rContainer1.begin());
280  if (*it2 == str2)
281  return { it1, it2 };
282  }
283  return { rContainer1.end(), rContainer2.end() };
284 }
285 
286 std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
287 SvxCharacterMap::getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
288 {
289  return findInPair(sTitle, maRecentCharList, rFont, maRecentCharFontList);
290 }
291 
292 std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
293 SvxCharacterMap::getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
294 {
295  return findInPair(sTitle, maFavCharList, rFont, maFavCharFontList);
296 }
297 
298 
300 {
301  assert(maRecentCharList.size() == maRecentCharFontList.size());
302 
303  int i = 0;
304  for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin();
305  it != maRecentCharList.end() && it2 != maRecentCharFontList.end();
306  ++it, ++it2, i++)
307  {
308  m_aRecentCharView[i].SetText(*it);
309  vcl::Font rFont = m_aRecentCharView[i].GetFont();
310  rFont.SetFamilyName( *it2 );
311  m_aRecentCharView[i].SetFont(rFont);
312  m_aRecentCharView[i].Show();
313  }
314 
315  for(; i < 16 ; i++)
316  {
317  m_aRecentCharView[i].SetText(OUString());
318  m_aRecentCharView[i].Hide();
319  }
320 }
321 
322 void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
323 {
324  // if recent char to be added is already in list, remove it
325  if( const auto& [itChar, itChar2] = getRecentChar(sTitle, rFont);
326  itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
327  {
328  maRecentCharList.erase( itChar );
329  maRecentCharFontList.erase( itChar2);
330  }
331 
332  if (maRecentCharList.size() == 16)
333  {
334  maRecentCharList.pop_back();
335  maRecentCharFontList.pop_back();
336  }
337 
338  maRecentCharList.push_front(sTitle);
339  maRecentCharFontList.push_front(rFont);
340 
341  css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
342  css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
343 
344  for (size_t i = 0; i < maRecentCharList.size(); ++i)
345  {
346  aRecentCharList[i] = maRecentCharList[i];
347  aRecentCharFontList[i] = maRecentCharFontList[i];
348  }
349 
350  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
351  officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
352  officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
353  batch->commit();
354 
356 }
357 
358 
359 void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
360 {
361  // if Fav char to be added is already in list, remove it
362  if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
363  itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
364  {
365  maFavCharList.erase( itChar );
366  maFavCharFontList.erase( itChar2);
367  }
368 
369  if (maFavCharList.size() == 16)
370  {
371  maFavCharList.pop_back();
372  maFavCharFontList.pop_back();
373  }
374 
375  maFavCharList.push_back(sTitle);
376  maFavCharFontList.push_back(rFont);
377 
378  css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
379  css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
380 
381  for (size_t i = 0; i < maFavCharList.size(); ++i)
382  {
383  aFavCharList[i] = maFavCharList[i];
384  aFavCharFontList[i] = maFavCharFontList[i];
385  }
386 
387  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
388  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
389  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
390  batch->commit();
391 }
392 
393 
395 {
396  assert(maFavCharList.size() == maFavCharFontList.size());
397 
398  int i = 0;
399  for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin();
400  it != maFavCharList.end() && it2 != maFavCharFontList.end();
401  ++it, ++it2, i++)
402  {
403  m_aFavCharView[i].SetText(*it);
404  vcl::Font rFont = m_aFavCharView[i].GetFont();
405  rFont.SetFamilyName( *it2 );
406  m_aFavCharView[i].SetFont(rFont);
407  m_aFavCharView[i].Show();
408  }
409 
410  for(; i < 16 ; i++)
411  {
412  m_aFavCharView[i].SetText(OUString());
413  m_aFavCharView[i].Hide();
414  }
415  m_xShowSet->getFavCharacterList();
416  m_xSearchSet->getFavCharacterList();
417 }
418 
419 void SvxCharacterMap::deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont)
420 {
421  // if Fav char is found, remove it
422  if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
423  itChar != maFavCharList.end() && itChar2 != maFavCharFontList.end() )
424  {
425  maFavCharList.erase( itChar );
426  maFavCharFontList.erase( itChar2);
427  }
428 
429  css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
430  css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
431 
432  for (size_t i = 0; i < maFavCharList.size(); ++i)
433  {
434  aFavCharList[i] = maFavCharList[i];
435  aFavCharFontList[i] = maFavCharFontList[i];
436  }
437 
438  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
439  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
440  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
441  batch->commit();
442 }
443 
445 {
446  aFont = m_xVirDev->GetFont();
447  aFont.SetTransparent( true );
450  aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
451 
452  OUString aDefStr( aFont.GetFamilyName() );
453  OUString aLastName;
454  int nCount = m_xVirDev->GetDevFontCount();
455  std::vector<weld::ComboBoxEntry> aEntries;
456  aEntries.reserve(nCount);
457  for (int i = 0; i < nCount; ++i)
458  {
459  OUString aFontName( m_xVirDev->GetDevFont( i ).GetFamilyName() );
460  if (aFontName != aLastName)
461  {
462  aLastName = aFontName;
463  aEntries.emplace_back(aFontName, OUString::number(i));
464  }
465  }
466  m_xFontLB->insert_vector(aEntries, true);
467  // the font may not be in the list =>
468  // try to find a font name token in list and select found font,
469  // else select topmost entry
470  bool bFound = (m_xFontLB->find_text(aDefStr) == -1);
471  if (!bFound)
472  {
473  sal_Int32 nIndex = 0;
474  do
475  {
476  OUString aToken = aDefStr.getToken(0, ';', nIndex);
477  if (m_xFontLB->find_text(aToken) != -1)
478  {
479  aDefStr = aToken;
480  bFound = true;
481  break;
482  }
483  }
484  while ( nIndex >= 0 );
485  }
486 
487  if (bFound)
488  m_xFontLB->set_active_text(aDefStr);
489  else if (m_xFontLB->get_count() )
490  m_xFontLB->set_active(0);
491  FontSelectHdl(*m_xFontLB);
492  if (m_xSubsetLB->get_count())
493  m_xSubsetLB->set_active(0);
494 
495  m_xFontLB->connect_changed(LINK( this, SvxCharacterMap, FontSelectHdl));
496  m_xSubsetLB->connect_changed(LINK( this, SvxCharacterMap, SubsetSelectHdl));
497  m_xOKBtn->connect_clicked(LINK(this, SvxCharacterMap, InsertClickHdl));
498  m_xOKBtn->show();
499 
500  m_xShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) );
501  m_xShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) );
502  m_xShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) );
503  m_xShowSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, CharPreSelectHdl ) );
504  m_xShowSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
505 
506  m_xSearchSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, SearchCharDoubleClickHdl ) );
507  m_xSearchSet->SetSelectHdl( LINK( this, SvxCharacterMap, SearchCharSelectHdl ) );
508  m_xSearchSet->SetHighlightHdl( LINK( this, SvxCharacterMap, SearchCharHighlightHdl ) );
509  m_xSearchSet->SetPreSelectHdl( LINK( this, SvxCharacterMap, SearchCharPreSelectHdl ) );
510  m_xSearchSet->SetFavClickHdl( LINK( this, SvxCharacterMap, FavClickHdl ) );
511 
512  m_xDecimalCodeText->connect_changed( LINK( this, SvxCharacterMap, DecimalCodeChangeHdl ) );
513  m_xHexCodeText->connect_changed( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) );
514  m_xFavouritesBtn->connect_clicked( LINK(this, SvxCharacterMap, FavSelectHdl));
515 
516  // tdf#117038 set the buttons width to its max possible width so it doesn't
517  // make layout change when the label changes
518  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
519  auto nMaxWidth = m_xFavouritesBtn->get_preferred_size().Width();
520  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
521  nMaxWidth = std::max(nMaxWidth, m_xFavouritesBtn->get_preferred_size().Width());
522  m_xFavouritesBtn->set_size_request(nMaxWidth, -1);
523 
524  if( SvxShowCharSet::getSelectedChar() == ' ')
525  {
526  m_xOKBtn->set_sensitive(false);
527  }
528  else
529  {
530  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
531  // using the new UCS4 constructor
532  OUString aOUStr( &cChar, 1 );
533  m_aShowChar.SetText(aOUStr);
534 
535  setFavButtonState(aOUStr, aDefStr);
536  m_xOKBtn->set_sensitive(true);
537  }
538 
541 
544 
545  bool bHasInsert = m_xFrame.is();
546 
547  for(int i = 0; i < 16; i++)
548  {
549  m_aRecentCharView[i].SetHasInsert(bHasInsert);
551  m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl));
552  m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl));
553  m_aFavCharView[i].SetHasInsert(bHasInsert);
554  m_aFavCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
555  m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl));
556  m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl));
557  }
558 
559  setCharName(90);
560 
561  m_xSearchText->connect_focus_in(LINK( this, SvxCharacterMap, SearchFieldGetFocusHdl ));
562  m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
563 }
564 
565 bool SvxCharacterMap::isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
566 {
567  const auto& [itChar, itFont] = getFavChar(sTitle, rFont);
568  return itChar != maFavCharList.end() && itFont != maFavCharFontList.end();
569 }
570 
571 
572 void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
573 {
574  if(sTitle.empty() || rFont.empty())
575  {
576  m_xFavouritesBtn->set_sensitive(false);
577  return;
578  }
579  else
580  m_xFavouritesBtn->set_sensitive(true);
581 
582  if (isFavChar(sTitle, rFont))
583  {
584  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_REMOVE_FAVORITES));
585  }
586  else
587  {
588  if(maFavCharList.size() == 16)
589  {
590  m_xFavouritesBtn->set_sensitive(false);
591  }
592 
593  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
594  }
595 }
596 
597 
599 {
600  // first get the underlying info in order to get font names
601  // like "Times New Roman;Times" resolved
602  vcl::Font aTmp(m_xVirDev->GetFontMetric(rFont));
603 
604  if (aTmp.GetFamilyName() == "StarSymbol" && m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
605  {
606  //if for some reason, like font in an old document, StarSymbol is requested and it's not available, then
607  //try OpenSymbol instead
608  aTmp.SetFamilyName("OpenSymbol");
609  }
610 
611  if (m_xFontLB->find_text(aTmp.GetFamilyName()) == -1)
612  return;
613 
614  m_xFontLB->set_active_text(aTmp.GetFamilyName());
615  aFont = aTmp;
616  FontSelectHdl(*m_xFontLB);
617  if (m_xSubsetLB->get_count())
618  m_xSubsetLB->set_active(0);
619 }
620 
622 {
623  SubsetMap aAll(nullptr);
624  std::vector<weld::ComboBoxEntry> aEntries;
625  for (auto & subset : aAll.GetSubsetMap())
626  aEntries.emplace_back(subset.GetName());
627  rListBox.insert_vector(aEntries, true);
628 }
629 
630 void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
631 {
632  if(sGlyph.isEmpty())
633  return;
634 
635  if (m_xFrame.is()) {
636  uno::Sequence<beans::PropertyValue> aArgs(2);
637  aArgs[0].Name = "Symbols";
638  aArgs[0].Value <<= sGlyph;
639 
640  aArgs[1].Name = "FontName";
641  aArgs[1].Value <<= aFont.GetFamilyName();
642  comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);
643 
645 
646  } else {
647  sal_UCS4 cChar = sGlyph.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
648  const SfxItemPool* pPool = m_xOutputSet->GetPool();
649  m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), sGlyph ) );
651  aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) );
652  m_xOutputSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), aFont.GetFamilyName() ) );
653  m_xOutputSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), cChar ) );
654  }
655 }
656 
658 {
659  const sal_uInt32 nFont = m_xFontLB->get_active_id().toUInt32();
660  aFont = m_xVirDev->GetDevFont(nFont);
661  aFont.SetWeight( WEIGHT_DONTKNOW );
662  aFont.SetItalic( ITALIC_NONE );
663  aFont.SetWidthType( WIDTH_DONTKNOW );
664  aFont.SetPitch( PITCH_DONTKNOW );
665  aFont.SetFamily( FAMILY_DONTKNOW );
666 
667  // notify children using this font
668  m_xShowSet->SetFont( aFont );
669  m_xSearchSet->SetFont( aFont );
670  m_aShowChar.SetFont( aFont );
671 
672  // setup unicode subset listbar with font specific subsets,
673  // hide unicode subset listbar for symbol fonts
674  // TODO: get info from the Font once it provides it
675  pSubsetMap.reset();
676  m_xSubsetLB->clear();
677 
678  bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
679  if (bNeedSubset)
680  {
681  FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
682  pSubsetMap.reset(new SubsetMap( xFontCharMap ));
683 
684  // update subset listbox for new font's unicode subsets
685  for (auto const& subset : pSubsetMap->GetSubsetMap())
686  {
687  m_xSubsetLB->append(OUString::number(reinterpret_cast<sal_uInt64>(&subset)), subset.GetName());
688  // NOTE: subset must live at least as long as the selected font
689  }
690 
691  if (m_xSubsetLB->get_count() <= 1)
692  bNeedSubset = false;
693  }
694 
695  m_xSubsetText->set_sensitive(bNeedSubset);
696  m_xSubsetLB->set_sensitive(bNeedSubset);
697 
698  if (isSearchMode)
699  {
700  // tdf#137294 do this after modifying m_xSubsetLB sensitivity to
701  // restore insensitive for the search case
702  SearchUpdateHdl(*m_xSearchText);
703  SearchCharHighlightHdl(m_xSearchSet.get());
704  }
705 
706  // tdf#118304 reselect current glyph to see if its still there in new font
707  selectCharByCode(Radix::hexadecimal);
708 }
709 
711 {
712  isSearchMode = state;
713  m_xHexCodeText->set_editable(!state);
714  m_xDecimalCodeText->set_editable(!state);
715  m_xSubsetLB->set_sensitive(!state);
716 
717  if(state)
718  {
719  m_xSearchSet->Show();
720  m_xShowSet->Hide();
721  }
722  else
723  {
724  m_xSearchSet->Hide();
725  m_xShowSet->Show();
726  }
727 }
728 
730 {
731  /* get the character name */
732  UErrorCode errorCode = U_ZERO_ERROR;
733  // icu has a private uprv_getMaxCharNameLength function which returns the max possible
734  // length of this property. Unicode 3.2 max char name length was 83
735  char buffer[100];
736  u_charName(nDecimalValue, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
737  if (U_SUCCESS(errorCode))
738  m_xCharName->set_label(OUString::createFromAscii(buffer));
739 }
740 
742 {
743  const sal_Int32 nPos = m_xSubsetLB->get_active();
744  const Subset* pSubset = reinterpret_cast<const Subset*>(m_xSubsetLB->get_active_id().toUInt64());
745 
746  if( pSubset && !isSearchMode)
747  {
748  sal_UCS4 cFirst = pSubset->GetRangeMin();
749  m_xShowSet->SelectCharacter( cFirst );
750 
751  setFavButtonState(OUString(&cFirst, 1), aFont.GetFamilyName());
752  m_xSubsetLB->set_active(nPos);
753  }
754  else if( pSubset && isSearchMode)
755  {
756  m_xSearchSet->SelectCharacter( pSubset );
757 
758  const Subset* curSubset = nullptr;
759  if( pSubsetMap )
760  curSubset = pSubsetMap->GetSubsetByUnicode( m_xSearchSet->GetSelectCharacter() );
761  if( curSubset )
762  m_xSubsetLB->set_active_text(curSubset->GetName());
763  else
764  m_xSubsetLB->set_active(-1);
765 
766  sal_UCS4 sChar = m_xSearchSet->GetSelectCharacter();
767  setFavButtonState(OUString(&sChar, 1), aFont.GetFamilyName());
768  }
769 }
770 
771 IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
772 {
773  const OUString& sTitle = rView->GetText();
774  OUString sFont = rView->GetFont().GetFamilyName();
775 
776  // if recent char to be added is already in list, remove it
777  if( const auto& [itChar, itChar2] = getRecentChar(sTitle, sFont);
778  itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() )
779  {
780  maRecentCharList.erase( itChar );
781  maRecentCharFontList.erase( itChar2);
782  }
783 
784  css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
785  css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
786 
787  for (size_t i = 0; i < maRecentCharList.size(); ++i)
788  {
789  aRecentCharList[i] = maRecentCharList[i];
790  aRecentCharFontList[i] = maRecentCharFontList[i];
791  }
792 
793  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
794  officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
795  officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
796  batch->commit();
797 
798  updateRecentCharControl();
799 }
800 
801 IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
802 {
803  css::uno::Sequence< OUString > aRecentCharList(0);
804  css::uno::Sequence< OUString > aRecentCharFontList(0);
805 
806  maRecentCharList.clear();
807  maRecentCharFontList.clear();
808 
809  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
810  officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
811  officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
812  batch->commit();
813 
814  updateRecentCharControl();
815 }
816 
817 IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
818 {
819  deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
820  updateFavCharControl();
821 }
822 
823 IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
824 {
825  css::uno::Sequence< OUString > aFavCharList(0);
826  css::uno::Sequence< OUString > aFavCharFontList(0);
827 
828  maFavCharList.clear();
829  maFavCharFontList.clear();
830 
831  std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(mxContext));
832  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
833  officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
834  batch->commit();
835 
836  updateFavCharControl();
837 }
838 
839 IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
840 {
841  m_xOKBtn->set_sensitive(false);
842 }
843 
844 IMPL_LINK_NOARG(SvxCharacterMap, SearchUpdateHdl, weld::Entry&, void)
845 {
846  if (!m_xSearchText->get_text().isEmpty())
847  {
848  m_xSearchSet->ClearPreviousData();
849  OUString aKeyword = m_xSearchText->get_text();
850 
851  toggleSearchView(true);
852 
853  FontCharMapRef xFontCharMap = m_xSearchSet->GetFontCharMap();
854 
855  sal_UCS4 sChar = xFontCharMap->GetFirstChar();
856  while(sChar != xFontCharMap->GetLastChar())
857  {
858  UErrorCode errorCode = U_ZERO_ERROR;
859  char buffer[100];
860  u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
861  if (U_SUCCESS(errorCode))
862  {
863  OUString sName = OUString::createFromAscii(buffer);
864  if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
865  m_xSearchSet->AppendCharToList(sChar);
866  }
867  sChar = xFontCharMap->GetNextChar(sChar);
868  }
869  //for last char
870  UErrorCode errorCode = U_ZERO_ERROR;
871  char buffer[100];
872  u_charName(sChar, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
873  if (U_SUCCESS(errorCode))
874  {
875  OUString sName = OUString::createFromAscii(buffer);
876  if(!sName.isEmpty() && sName.toAsciiLowerCase().indexOf(aKeyword.toAsciiLowerCase()) >= 0)
877  m_xSearchSet->AppendCharToList(sChar);
878  }
879  }
880  else
881  {
882  toggleSearchView(false);
883  }
884 }
885 
886 
887 IMPL_LINK(SvxCharacterMap, CharClickHdl, SvxCharView*, rView, void)
888 {
889  rView->GrabFocus();
890 
891  m_aShowChar.SetText( rView->GetText() );
892  m_aShowChar.SetFont(rView->GetFont());
893  m_aShowChar.Invalidate();
894 
895  setFavButtonState(rView->GetText(), rView->GetFont().GetFamilyName());//check state
896 
897  // Get the hexadecimal code
898  OUString charValue = rView->GetText();
899  sal_UCS4 cChar = charValue.iterateCodePoints(&o3tl::temporary(sal_Int32(1)), -1);
900  OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
901 
902  // Get the decimal code
903  OUString aDecimalText = OUString::number(cChar);
904 
905  m_xHexCodeText->set_text(aHexText);
906  m_xDecimalCodeText->set_text(aDecimalText);
907  setCharName(cChar);
908 
909  rView->Invalidate();
910  m_xOKBtn->set_sensitive(true);
911 }
912 
913 IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void)
914 {
915  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
916  // using the new UCS4 constructor
917  OUString aOUStr( &cChar, 1 );
918  setFavButtonState(aOUStr, aFont.GetFamilyName());
919  insertCharToDoc(aOUStr);
920 }
921 
922 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharDoubleClickHdl, SvxShowCharSet*, void)
923 {
924  sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
925  // using the new UCS4 constructor
926  OUString aOUStr( &cChar, 1 );
927  setFavButtonState(aOUStr, aFont.GetFamilyName());
928  insertCharToDoc(aOUStr);
929 }
930 
932 {
933  m_xOKBtn->set_sensitive(true);
934 }
935 
936 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharSelectHdl, SvxShowCharSet*, void)
937 {
938  m_xOKBtn->set_sensitive(true);
939 }
940 
942 {
943  OUString sChar = m_aShowChar.GetText();
944  insertCharToDoc(sChar);
945  // Need to update recent character list, when OK button does not insert
946  if(!m_xFrame.is())
947  updateRecentCharacterList(sChar, aFont.GetFamilyName());
948  m_xDialog->response(RET_OK);
949 }
950 
952 {
953  if (m_xFavouritesBtn->get_label().match(CuiResId(RID_SVXSTR_ADD_FAVORITES)))
954  {
955  updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
956  setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
957  }
958  else
959  {
960  deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
961  m_xFavouritesBtn->set_label(CuiResId(RID_SVXSTR_ADD_FAVORITES));
962  m_xFavouritesBtn->set_sensitive(false);
963  }
964 
965  updateFavCharControl();
966 }
967 
969 {
970  getFavCharacterList();
971  updateFavCharControl();
972 }
973 
975 {
976  OUString aText;
977  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
978  bool bSelect = (cChar > 0);
979 
980  // show char sample
981  if ( bSelect )
982  {
983  // using the new UCS4 constructor
984  aText = OUString( &cChar, 1 );
985  // Get the hexadecimal code
986  OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
987  // Get the decimal code
988  OUString aDecimalText = OUString::number(cChar);
989  setCharName(cChar);
990 
991  // Update the hex and decimal codes only if necessary
992  if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
993  m_xHexCodeText->set_text(aHexText);
994  if (m_xDecimalCodeText->get_text() != aDecimalText)
995  m_xDecimalCodeText->set_text( aDecimalText );
996 
997  const Subset* pSubset = nullptr;
998  if( pSubsetMap )
999  pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1000  if( pSubset )
1001  m_xSubsetLB->set_active_text(pSubset->GetName());
1002  else
1003  m_xSubsetLB->set_active(-1);
1004  }
1005 
1006  m_aShowChar.SetText( aText );
1007  m_aShowChar.SetFont( aFont );
1008  m_aShowChar.Invalidate();
1009 
1010  setFavButtonState(aText, aFont.GetFamilyName());
1011 }
1012 
1013 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharHighlightHdl, SvxShowCharSet*, void)
1014 {
1015  OUString aText;
1016  sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1017  bool bSelect = (cChar > 0);
1018 
1019  // show char sample
1020  if ( bSelect )
1021  {
1022  aText = OUString( &cChar, 1 );
1023  // Get the hexadecimal code
1024  OUString aHexText = OUString::number(cChar, 16).toAsciiUpperCase();
1025  // Get the decimal code
1026  OUString aDecimalText = OUString::number(cChar);
1027  setCharName(cChar);
1028 
1029  // Update the hex and decimal codes only if necessary
1030  if (!m_xHexCodeText->get_text().equalsIgnoreAsciiCase(aHexText))
1031  m_xHexCodeText->set_text(aHexText);
1032  if (m_xDecimalCodeText->get_text() != aDecimalText)
1033  m_xDecimalCodeText->set_text( aDecimalText );
1034 
1035  const Subset* pSubset = nullptr;
1036  if( pSubsetMap )
1037  pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1038  if( pSubset )
1039  m_xSubsetLB->set_active_text(pSubset->GetName());
1040  else
1041  m_xSubsetLB->set_active(-1);
1042  }
1043 
1044  if(m_xSearchSet->HasFocus())
1045  {
1046  m_aShowChar.SetText( aText );
1047  m_aShowChar.SetFont( aFont );
1048  m_aShowChar.Invalidate();
1049 
1050  setFavButtonState(aText, aFont.GetFamilyName());
1051  }
1052 }
1053 
1055 {
1056  OUString aCodeString;
1057  switch(radix)
1058  {
1059  case Radix::decimal:
1060  aCodeString = m_xDecimalCodeText->get_text();
1061  break;
1062  case Radix::hexadecimal:
1063  aCodeString = m_xHexCodeText->get_text();
1064  break;
1065  }
1066  // Convert the code back to a character using the appropriate radix
1067  sal_UCS4 cChar = aCodeString.toUInt32(static_cast<sal_Int16> (radix));
1068  // Use FontCharMap::HasChar(sal_UCS4 cChar) to see if the desired character is in the font
1069  FontCharMapRef xFontCharMap = m_xShowSet->GetFontCharMap();
1070  if (xFontCharMap->HasChar(cChar))
1071  // Select the corresponding character
1072  SetChar(cChar);
1073  else {
1074  m_xCharName->set_label(CuiResId(RID_SVXSTR_MISSING_CHAR));
1075  m_aShowChar.SetText(" ");
1076  switch(radix)
1077  {
1078  case Radix::decimal:
1079  m_xHexCodeText->set_text(OUString::number(cChar, 16));
1080  break;
1081  case Radix::hexadecimal:
1082  m_xDecimalCodeText->set_text(OUString::number(cChar));
1083  break;
1084  }
1085  }
1086 }
1087 
1088 IMPL_LINK_NOARG(SvxCharacterMap, DecimalCodeChangeHdl, weld::Entry&, void)
1089 {
1090  selectCharByCode(Radix::decimal);
1091 }
1092 
1093 IMPL_LINK_NOARG(SvxCharacterMap, HexCodeChangeHdl, weld::Entry&, void)
1094 {
1095  selectCharByCode(Radix::hexadecimal);
1096 }
1097 
1099 {
1100  // adjust subset selection
1101  if( pSubsetMap )
1102  {
1103  sal_UCS4 cChar = m_xShowSet->GetSelectCharacter();
1104 
1105  setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1106  const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1107  if( pSubset )
1108  m_xSubsetLB->set_active_text(pSubset->GetName());
1109  }
1110 
1111  m_xOKBtn->set_sensitive(true);
1112 }
1113 
1114 IMPL_LINK_NOARG(SvxCharacterMap, SearchCharPreSelectHdl, SvxShowCharSet*, void)
1115 {
1116  // adjust subset selection
1117  if( pSubsetMap )
1118  {
1119  sal_UCS4 cChar = m_xSearchSet->GetSelectCharacter();
1120 
1121  setFavButtonState(OUString(&cChar, 1), aFont.GetFamilyName());
1122  const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
1123  if( pSubset )
1124  m_xSubsetLB->set_active_text(pSubset->GetName());
1125  }
1126 
1127  m_xOKBtn->set_sensitive(true);
1128 }
1129 
1130 // class SvxShowText =====================================================
1132  : m_xVirDev(rVirDev)
1133  , mnY(0)
1134  , mbCenter(false)
1135 {
1136 }
1137 
1139 {
1140  CustomWidgetController::SetDrawingArea(pDrawingArea);
1141  vcl::Font aFont = m_xVirDev->GetFont();
1142  Size aFontSize(aFont.GetFontSize().Width() * 5, aFont.GetFontSize().Height() * 5);
1143  aFont.SetFontSize(aFontSize);
1144  m_xVirDev->Push(PUSH_ALLFONT);
1145  m_xVirDev->SetFont(aFont);
1146  pDrawingArea->set_size_request(m_xVirDev->approximate_digit_width() + 2 * 12,
1147  m_xVirDev->LogicToPixel(aFontSize).Height() * 2);
1148  m_xVirDev->Pop();
1149 }
1150 
1152 {
1153  rRenderContext.SetFont(m_aFont);
1154 
1155  Color aTextCol = rRenderContext.GetTextColor();
1156  Color aFillCol = rRenderContext.GetFillColor();
1157 
1158  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1159  const Color aWindowTextColor(rStyleSettings.GetDialogTextColor());
1160  const Color aWindowColor(rStyleSettings.GetWindowColor());
1161  rRenderContext.SetTextColor(aWindowTextColor);
1162  rRenderContext.SetFillColor(aWindowColor);
1163 
1164  const OUString aText = GetText();
1165 
1166  Size aSize(GetOutputSizePixel());
1167  tools::Long nAvailWidth = aSize.Width();
1168  tools::Long nWinHeight = aSize.Height();
1169 
1170  bool bGotBoundary = true;
1171  bool bShrankFont = false;
1172  vcl::Font aOrigFont(rRenderContext.GetFont());
1173  Size aFontSize(aOrigFont.GetFontSize());
1174  ::tools::Rectangle aBoundRect;
1175 
1176  for (tools::Long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5)
1177  {
1178  if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty())
1179  {
1180  bGotBoundary = false;
1181  break;
1182  }
1183  if (!mbCenter)
1184  break;
1185  //only shrink in the single glyph large view mode
1186  tools::Long nTextWidth = aBoundRect.GetWidth();
1187  if (nAvailWidth > nTextWidth)
1188  break;
1189  vcl::Font aFont(aOrigFont);
1190  aFontSize.setHeight( nFontHeight );
1191  aFont.SetFontSize(aFontSize);
1192  rRenderContext.SetFont(aFont);
1193  mnY = (nWinHeight - rRenderContext.GetTextHeight()) / 2;
1194  bShrankFont = true;
1195  }
1196 
1197  Point aPoint(2, mnY);
1198  // adjust position using ink boundary if possible
1199  if (!bGotBoundary)
1200  aPoint.setX( (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2 );
1201  else
1202  {
1203  // adjust position before it gets out of bounds
1204  aBoundRect += aPoint;
1205 
1206  // shift back vertically if needed
1207  int nYLDelta = aBoundRect.Top();
1208  int nYHDelta = aSize.Height() - aBoundRect.Bottom();
1209  if( nYLDelta <= 0 )
1210  aPoint.AdjustY( -(nYLDelta - 1) );
1211  else if( nYHDelta <= 0 )
1212  aPoint.AdjustY(nYHDelta - 1 );
1213 
1214  if (mbCenter)
1215  {
1216  // move glyph to middle of cell
1217  aPoint.setX( -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2 );
1218  }
1219  else
1220  {
1221  // shift back horizontally if needed
1222  int nXLDelta = aBoundRect.Left();
1223  int nXHDelta = aSize.Width() - aBoundRect.Right();
1224  if( nXLDelta <= 0 )
1225  aPoint.AdjustX( -(nXLDelta - 1) );
1226  else if( nXHDelta <= 0 )
1227  aPoint.AdjustX(nXHDelta - 1 );
1228  }
1229  }
1230 
1231  rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize));
1232  rRenderContext.DrawText(aPoint, aText);
1233  rRenderContext.SetTextColor(aTextCol);
1234  rRenderContext.SetFillColor(aFillCol);
1235  if (bShrankFont)
1236  rRenderContext.SetFont(aOrigFont);
1237 }
1238 
1239 void SvxShowText::SetFont( const vcl::Font& rFont )
1240 {
1241  tools::Long nWinHeight = GetOutputSizePixel().Height();
1242 
1243  m_aFont = rFont;
1246  m_aFont.SetFontSize(m_xVirDev->PixelToLogic(Size(0, nWinHeight / 2)));
1247  m_aFont.SetTransparent(true);
1248 
1249  m_xVirDev->Push(PUSH_ALLFONT);
1250  m_xVirDev->SetFont(m_aFont);
1251  mnY = (nWinHeight - m_xVirDev->GetTextHeight()) / 2;
1252  m_xVirDev->Pop();
1253 
1254  Invalidate();
1255 }
1256 
1258 {
1259  SetFont(GetFont()); //force recalculation of size
1260 }
1261 
1262 void SvxShowText::SetText(const OUString& rText)
1263 {
1264  m_sText = rText;
1265  Invalidate();
1266 }
1267 
1268 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void updateRecentCharControl()
Definition: cuicharmap.cxx:299
void SetFamily(FontFamily)
const Color & GetTextColor() const
bool HasChar(sal_UCS4) const
sal_Int32 GetValue() const
SvxCharView m_aFavCharView[16]
Definition: cuicharmap.hxx:93
sal_Int32 nIndex
void SetFontSize(const Size &)
SvxShowText m_aShowChar
Definition: cuicharmap.hxx:94
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:52
const OUString & GetFamilyName() const
tools::Long mnY
Definition: cuicharmap.hxx:54
sal_uInt32 sal_UCS4
const OUString & GetStyleName() const
const SubsetVec & GetSubsetMap() const
uno::Reference< uno::XComponentContext > mxContext
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &) override
long Long
FAMILY_DONTKNOW
const OUString & GetName() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
std::unique_ptr< SvxSearchCharSet > m_xSearchSet
Definition: cuicharmap.hxx:113
void SetChar(sal_UCS4)
Definition: cuicharmap.cxx:205
css::uno::Reference< css::lang::XComponent > m_xFrame
void SetWeight(FontWeight)
void SetFont(const vcl::Font &rFont)
std::deque< OUString > maRecentCharList
Definition: cuicharmap.hxx:86
void setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
Definition: cuicharmap.cxx:572
static void fillAllSubsets(weld::ComboBox &rListBox)
Definition: cuicharmap.cxx:621
void insertCharToDoc(const OUString &sChar)
Definition: cuicharmap.cxx:630
void SetCharSet(rtl_TextEncoding)
std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
Definition: cuicharmap.cxx:293
FontPitch GetPitch() const
OUString const & GetText() const
Definition: cuicharmap.hxx:68
ScopedVclPtr< VirtualDevice > m_xVirDev
Definition: cuicharmap.hxx:81
std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
Definition: cuicharmap.cxx:287
Size const & GetOutputSizePixel() const
FontFamily GetFamilyType()
void selectCharByCode(Radix radix)
OUString CuiResId(std::string_view aKey)
Definition: cuiresmgr.cxx:23
SfxApplication * SfxGetpApp()
std::unique_ptr< SfxAllItemSet > m_xOutputSet
Definition: cuicharmap.hxx:116
OUString m_sText
Definition: cuicharmap.hxx:53
constexpr tools::Long Width() const
void toggleSearchView(bool state)
Definition: cuicharmap.cxx:710
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
const vcl::Font & GetFont() const
std::unique_ptr< weld::Label > m_xFontText
Definition: cuicharmap.hxx:97
static sal_uInt32 & getSelectedChar()
rtl_TextEncoding GetCharSet() const
bool dispatchCommand(const OUString &rCommand, const uno::Reference< css::frame::XFrame > &rFrame, const css::uno::Sequence< css::beans::PropertyValue > &rArguments, const uno::Reference< css::frame::XDispatchResultListener > &rListener)
void deleteFavCharacterFromList(std::u16string_view rChar, std::u16string_view rFont)
Definition: cuicharmap.cxx:419
int nCount
constexpr tools::Long GetWidth() const
static std::shared_ptr< ConfigurationChanges > create(css::uno::Reference< css::uno::XComponentContext > const &context=comphelper::getProcessComponentContext())
std::unique_ptr< weld::ComboBox > m_xSubsetLB
Definition: cuicharmap.hxx:100
std::deque< OUString > maFavCharList
Definition: cuicharmap.hxx:88
void setCharName(sal_UCS4 nDecimalValue)
Definition: cuicharmap.cxx:729
const char * sName
void DrawRect(const tools::Rectangle &rRect)
void SetPitch(FontPitch ePitch)
SfxItemPool & GetPool() const
const OUString & GetStyleName() const
std::unique_ptr< weld::Entry > m_xDecimalCodeText
Definition: cuicharmap.hxx:103
uno::Reference< uno::XComponentContext > mxContext
Definition: cuicharmap.hxx:90
bool isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
Definition: cuicharmap.cxx:565
css::uno::Reference< css::frame::XFrame > m_xFrame
Definition: cuicharmap.hxx:85
WEIGHT_DONTKNOW
void SetAlignment(FontAlign)
std::unique_ptr< SvxShowCharSet > m_xShowSet
Definition: cuicharmap.hxx:111
void updateRecentCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:322
sal_UCS4 GetFirstChar() const
std::unique_ptr< weld::Button > m_xFavouritesBtn
Definition: cuicharmap.hxx:104
void SetFamilyName(const OUString &rFamilyName)
void getRecentCharacterList()
Definition: cuicharmap.cxx:223
void SetFont(const vcl::Font &rFont)
FontPitch GetPitch()
int i
void SetHasInsert(bool bInsert)
virtual void insert_vector(const std::vector< weld::ComboBoxEntry > &rItems, bool bKeepExisting)=0
vcl::Font m_aFont
Definition: cuicharmap.hxx:56
std::unique_ptr< weld::Entry > m_xHexCodeText
Definition: cuicharmap.hxx:102
void SetFillColor()
WEIGHT_NORMAL
float u
void SetTextColor(const Color &rColor)
void setClearAllClickHdl(const Link< SvxCharView *, void > &rLink)
const Size & GetFontSize() const
PITCH_DONTKNOW
void getFavCharacterList()
Definition: cuicharmap.cxx:246
void updateFavCharacterList(const OUString &rChar, const OUString &rFont)
Definition: cuicharmap.cxx:359
ITALIC_NONE
std::unique_ptr< weld::Entry > m_xSearchText
Definition: cuicharmap.hxx:101
vcl::Font aFont
Definition: cuicharmap.hxx:82
#define PUSH_ALLFONT
void SetText(const OUString &rText)
sal_UCS4 GetRangeMin() const
constexpr T & temporary(T &&x)
virtual short run() override
Definition: cuicharmap.cxx:184
SvxCharacterMap(weld::Widget *pParent, const SfxItemSet *pSet, const css::uno::Reference< css::frame::XFrame > &rFrame)
Definition: cuicharmap.cxx:51
IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView *, rView, void)
Definition: cuicharmap.cxx:771
const OUString & GetFamilyName() const
sal_UCS4 GetNextChar(sal_UCS4 cChar) const
std::deque< OUString > maFavCharFontList
Definition: cuicharmap.hxx:89
ALIGN_TOP
void setClearClickHdl(const Link< SvxCharView *, void > &rLink)
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
constexpr tools::Long Height() const
void setMouseClickHdl(const Link< SvxCharView *, void > &rLink)
WIDTH_DONTKNOW
std::deque< OUString > maRecentCharFontList
Definition: cuicharmap.hxx:87
void SetFont(const vcl::Font &rNewFont)
void SetTransparent(bool bTransparent)
tools::Long GetTextHeight() const
SvxShowText(const VclPtr< VirtualDevice > &rVirDev)
sal_UCS4 GetLastChar() const
RET_OK
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Reference< XExecutableDialog > m_xDialog
Reference< XComponentContext > getProcessComponentContext()
void SetCharFont(const vcl::Font &rFont)
Definition: cuicharmap.cxx:598
void updateFavCharControl()
Definition: cuicharmap.cxx:394
const Color & GetWindowColor() const
virtual void SetDrawingArea(weld::DrawingArea *pDrawingArea) override
void DisableFontSelection()
Definition: cuicharmap.cxx:216
static std::pair< std::deque< OUString >::const_iterator, std::deque< OUString >::const_iterator > findInPair(std::u16string_view str1, const std::deque< OUString > &rContainer1, std::u16string_view str2, const std::deque< OUString > &rContainer2)
Definition: cuicharmap.cxx:271
FILE * init(int, char **)
std::unique_ptr< weld::ComboBox > m_xFontLB
Definition: cuicharmap.hxx:98
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, const tools::Long *pDXArray=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
void SetText(const OUString &rText)
ScXMLEditAttributeMap::Entry const aEntries[]
sal_UCS4 GetChar() const
Definition: cuicharmap.cxx:211
vcl::Font const & GetFont() const
Definition: cuicharmap.hxx:66
The main purpose of this dialog is to enable the use of characters that are not easily accessible fro...
Definition: cuicharmap.hxx:76
IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, weld::ComboBox &, void)
Definition: cuicharmap.cxx:657
std::unique_ptr< weld::Button > m_xOKBtn
Definition: cuicharmap.hxx:96
const Color & GetDialogTextColor() const
virtual void set_size_request(int nWidth, int nHeight)=0
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
vcl::Font const & GetFont() const
rtl_TextEncoding GetCharSet() const
sal_uInt16 nPos
virtual void Resize() override
const Color & GetFillColor() const
SvxCharView m_aRecentCharView[16]
Definition: cuicharmap.hxx:92
std::unique_ptr< weld::Label > m_xCharName
Definition: cuicharmap.hxx:105