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