Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/accmgr.cxx
Line
Count
Source
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
21
#include <accel.hxx>
22
#include <accmgr.hxx>
23
24
#include <algorithm>
25
26
ImplAccelManager::~ImplAccelManager()
27
0
{
28
0
}
29
30
bool ImplAccelManager::InsertAccel( Accelerator* pAccel )
31
0
{
32
0
    if ( !mxAccelList ) {
33
0
        mxAccelList.emplace();
34
0
    } else {
35
0
        for (Accelerator* i : *mxAccelList) {
36
0
            if ( i == pAccel ) {
37
0
                return false;
38
0
            }
39
0
        }
40
0
    }
41
42
0
    mxAccelList->insert( mxAccelList->begin(), pAccel );
43
0
    return true;
44
0
}
45
46
void ImplAccelManager::RemoveAccel( Accelerator const * pAccel )
47
0
{
48
    // do we have a list ?
49
0
    if ( !mxAccelList )
50
0
        return;
51
52
    //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't
53
    //end it, and then closes the dialog, deleting the accelerators. So if
54
    //we're removing an accelerator that a sub-accelerator which is in the
55
    //sequence list, throw away the entire sequence
56
0
    if ( mxSequenceList ) {
57
0
        for (sal_uInt16 i = 0; i < pAccel->GetItemCount(); ++i) {
58
0
            Accelerator* pSubAccel = pAccel->GetAccel( pAccel->GetItemId(i) );
59
0
            for (Accelerator* j : *mxSequenceList) {
60
0
                if ( j == pSubAccel ) {
61
0
                    EndSequence();
62
0
                    i = pAccel->GetItemCount();
63
0
                    break;
64
0
                }
65
0
            }
66
0
        }
67
0
    }
68
69
    // throw it away
70
0
    auto it = std::find(mxAccelList->begin(), mxAccelList->end(), pAccel);
71
0
    if (it != mxAccelList->end())
72
0
        mxAccelList->erase( it );
73
0
}
74
75
void ImplAccelManager::EndSequence()
76
0
{
77
    // are we in a list ?
78
0
    if ( !mxSequenceList )
79
0
        return;
80
81
0
    for (Accelerator* pTempAccel : *mxSequenceList)
82
0
    {
83
0
        pTempAccel->mpDel = nullptr;
84
0
    }
85
86
    // delete sequence-list
87
0
    mxSequenceList.reset();
88
0
}
89
90
bool ImplAccelManager::IsAccelKey( const vcl::KeyCode& rKeyCode )
91
0
{
92
0
    Accelerator* pAccel;
93
94
    // do we have accelerators ??
95
0
    if ( !mxAccelList )
96
0
        return false;
97
0
    if ( mxAccelList->empty() )
98
0
        return false;
99
100
    // are we in a sequence ?
101
0
    if ( mxSequenceList )
102
0
    {
103
0
        pAccel = mxSequenceList->empty() ? nullptr : (*mxSequenceList)[ 0 ];
104
105
        // not found ?
106
0
        if ( !pAccel )
107
0
        {
108
            // abort sequence
109
0
            FlushAccel();
110
0
            return false;
111
0
        }
112
113
        // can the entry be found ?
114
0
        ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
115
0
        if ( pEntry )
116
0
        {
117
0
            Accelerator* pNextAccel = pEntry->mpAccel;
118
119
            // is an accelerator coupled ?
120
0
            if ( pNextAccel )
121
0
            {
122
123
0
                mxSequenceList->insert( mxSequenceList->begin(), pNextAccel );
124
125
                // call Activate-Handler of the new one
126
0
                pNextAccel->Activate();
127
0
                return true;
128
0
            }
129
0
            else
130
0
            {
131
                // it is there already !
132
0
                if ( pEntry->mbEnabled )
133
0
                {
134
                    // stop sequence (first call deactivate-handler)
135
0
                    EndSequence();
136
137
                    // set accelerator of the actual item
138
                    // and call the handler
139
0
                    bool bDel = false;
140
0
                    pAccel->mnCurId         = pEntry->mnId;
141
0
                    pAccel->mpDel           = &bDel;
142
0
                    pAccel->Select();
143
144
                    // did the accelerator survive the call
145
0
                    if ( !bDel )
146
0
                    {
147
0
                        pAccel->mnCurId         = 0;
148
0
                        pAccel->mpDel           = nullptr;
149
0
                    }
150
151
0
                    return true;
152
0
                }
153
0
                else
154
0
                {
155
                    // stop sequence as the accelerator was disabled
156
                    // transfer the key (to the system)
157
0
                    FlushAccel();
158
0
                    return false;
159
0
                }
160
0
            }
161
0
        }
162
0
        else
163
0
        {
164
            // wrong key => stop sequence
165
0
            FlushAccel();
166
0
            return false;
167
0
        }
168
0
    }
169
170
    // step through the list of accelerators
171
0
    for (Accelerator* i : *mxAccelList)
172
0
    {
173
0
        pAccel = i;
174
175
        // is the entry contained ?
176
0
        ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
177
0
        if ( pEntry )
178
0
        {
179
0
            Accelerator* pNextAccel = pEntry->mpAccel;
180
181
            // is an accelerator assigned ?
182
0
            if ( pNextAccel )
183
0
            {
184
185
                // create sequence list
186
0
                mxSequenceList.emplace();
187
0
                mxSequenceList->insert( mxSequenceList->begin(), pAccel     );
188
0
                mxSequenceList->insert( mxSequenceList->begin(), pNextAccel );
189
190
                // call activate-Handler of the new one
191
0
                pNextAccel->Activate();
192
193
0
                return true;
194
0
            }
195
0
            else
196
0
            {
197
                // already assigned !
198
0
                if ( pEntry->mbEnabled )
199
0
                {
200
                    // first call activate/deactivate-Handler
201
0
                    pAccel->Activate();
202
203
                    // define accelerator of the actual item
204
                    // and call the handler
205
0
                    bool bDel = false;
206
0
                    pAccel->mnCurId         = pEntry->mnId;
207
0
                    pAccel->mpDel           = &bDel;
208
0
                    pAccel->Select();
209
210
                    // if the accelerator did survive the call
211
0
                    if ( !bDel )
212
0
                    {
213
0
                        pAccel->mnCurId         = 0;
214
0
                        pAccel->mpDel           = nullptr;
215
0
                    }
216
217
0
                    return true;
218
0
                }
219
0
                else
220
0
                    return false;
221
0
            }
222
0
        }
223
0
    }
224
225
0
    return false;
226
0
}
227
228
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */