Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <tools/rcid.h>
30 : : #include <vcl/spin.h>
31 : : #include <vcl/event.hxx>
32 : : #include <vcl/spin.hxx>
33 : :
34 : : // =======================================================================
35 : :
36 : 2 : void SpinButton::ImplInit( Window* pParent, WinBits nStyle )
37 : : {
38 : 2 : mbUpperIn = sal_False;
39 : 2 : mbLowerIn = sal_False;
40 : 2 : mbInitialUp = sal_False;
41 : 2 : mbInitialDown = sal_False;
42 : :
43 : 2 : mnMinRange = 0;
44 : 2 : mnMaxRange = 100;
45 : 2 : mnValue = 0;
46 : 2 : mnValueStep = 1;
47 : :
48 : 2 : maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
49 : 2 : maRepeatTimer.SetTimeoutHdl( LINK( this, SpinButton, ImplTimeout ) );
50 : :
51 : 2 : mbRepeat = 0 != ( nStyle & WB_REPEAT );
52 : :
53 [ - + ]: 2 : if ( nStyle & WB_HSCROLL )
54 : 0 : mbHorz = sal_True;
55 : : else
56 : 2 : mbHorz = sal_False;
57 : :
58 : 2 : Control::ImplInit( pParent, nStyle, NULL );
59 : 2 : }
60 : :
61 : : // -----------------------------------------------------------------------
62 : :
63 : 2 : SpinButton::SpinButton( Window* pParent, WinBits nStyle )
64 : : :Control( WINDOW_SPINBUTTON )
65 [ + - ][ + - ]: 2 : ,mbUpperIsFocused( sal_False )
[ + - ][ + - ]
[ + - ][ + - ]
66 : : {
67 [ + - ]: 2 : ImplInit( pParent, nStyle );
68 : 2 : }
69 : :
70 : : // -----------------------------------------------------------------------
71 : :
72 [ + - ]: 2 : SpinButton::~SpinButton()
73 : : {
74 [ - + ]: 4 : }
75 : :
76 : : // -----------------------------------------------------------------------
77 : :
78 : 0 : IMPL_LINK( SpinButton, ImplTimeout, Timer*, pTimer )
79 : : {
80 [ # # ]: 0 : if ( pTimer->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
81 : : {
82 : 0 : pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
83 : 0 : pTimer->Start();
84 : : }
85 : : else
86 : : {
87 [ # # ]: 0 : if ( mbInitialUp )
88 : 0 : Up();
89 : : else
90 : 0 : Down();
91 : : }
92 : :
93 : 0 : return 0;
94 : : }
95 : :
96 : : // -----------------------------------------------------------------------
97 : :
98 : 0 : void SpinButton::Up()
99 : : {
100 [ # # ]: 0 : if ( ImplIsUpperEnabled() )
101 : : {
102 : 0 : mnValue += mnValueStep;
103 : 0 : StateChanged( STATE_CHANGE_DATA );
104 : :
105 : 0 : ImplMoveFocus( sal_True );
106 : : }
107 : :
108 : 0 : ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_UP, maUpHdlLink, this );
109 : 0 : }
110 : :
111 : : // -----------------------------------------------------------------------
112 : :
113 : 0 : void SpinButton::Down()
114 : : {
115 [ # # ]: 0 : if ( ImplIsLowerEnabled() )
116 : : {
117 : 0 : mnValue -= mnValueStep;
118 : 0 : StateChanged( STATE_CHANGE_DATA );
119 : :
120 : 0 : ImplMoveFocus( sal_False );
121 : : }
122 : :
123 : 0 : ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_DOWN, maDownHdlLink, this );
124 : 0 : }
125 : :
126 : : // -----------------------------------------------------------------------
127 : :
128 : 6 : void SpinButton::Resize()
129 : : {
130 [ + - ]: 6 : Control::Resize();
131 : :
132 : 6 : Size aSize( GetOutputSizePixel() );
133 : 6 : Point aTmpPoint;
134 [ + - ]: 6 : Rectangle aRect( aTmpPoint, aSize );
135 [ + - ]: 6 : if ( mbHorz )
136 : : {
137 [ + - ]: 6 : maLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
138 [ + - ][ + - ]: 6 : maUpperRect = Rectangle( maLowerRect.TopRight(), aRect.BottomRight() );
[ + - ]
139 : : }
140 : : else
141 : : {
142 [ # # ]: 0 : maUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
143 [ # # ][ # # ]: 0 : maLowerRect = Rectangle( maUpperRect.BottomLeft(), aRect.BottomRight() );
[ # # ]
144 : : }
145 : :
146 [ - + ][ # # ]: 6 : ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() );
147 : :
148 [ + - ]: 6 : Invalidate();
149 : 6 : }
150 : :
151 : : // -----------------------------------------------------------------------
152 : :
153 : 0 : void SpinButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
154 : : {
155 [ # # ]: 0 : Point aPos = pDev->LogicToPixel( rPos );
156 [ # # ]: 0 : Size aSize = pDev->LogicToPixel( rSize );
157 : :
158 [ # # ]: 0 : pDev->Push();
159 [ # # ]: 0 : pDev->SetMapMode();
160 [ # # ]: 0 : if ( !(nFlags & WINDOW_DRAW_MONO) )
161 : : {
162 : : // DecoView uses the FaceColor...
163 [ # # ]: 0 : AllSettings aSettings = pDev->GetSettings();
164 [ # # ]: 0 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
165 [ # # ][ # # ]: 0 : if ( IsControlBackground() )
166 [ # # ][ # # ]: 0 : aStyleSettings.SetFaceColor( GetControlBackground() );
167 : : else
168 [ # # ]: 0 : aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
169 : :
170 [ # # ]: 0 : aSettings.SetStyleSettings( aStyleSettings );
171 [ # # ][ # # ]: 0 : pDev->SetSettings( aSettings );
[ # # ]
172 : : }
173 : :
174 [ # # ]: 0 : Rectangle aRect( Point( 0, 0 ), aSize );
175 [ # # ][ # # ]: 0 : Rectangle aLowerRect, aUpperRect;
176 [ # # ]: 0 : if ( mbHorz )
177 : : {
178 [ # # ]: 0 : aLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
179 [ # # ][ # # ]: 0 : aUpperRect = Rectangle( aLowerRect.TopRight(), aRect.BottomRight() );
[ # # ]
180 : : }
181 : : else
182 : : {
183 [ # # ]: 0 : aUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
184 [ # # ][ # # ]: 0 : aLowerRect = Rectangle( aUpperRect.BottomLeft(), aRect.BottomRight() );
[ # # ]
185 : : }
186 : :
187 [ # # ]: 0 : aUpperRect += aPos;
188 [ # # ]: 0 : aLowerRect += aPos;
189 : :
190 : : ImplDrawSpinButton( pDev, aUpperRect, aLowerRect, sal_False, sal_False,
191 [ # # ]: 0 : IsEnabled() && ImplIsUpperEnabled(),
192 [ # # ][ # # ]: 0 : IsEnabled() && ImplIsLowerEnabled(), mbHorz, sal_True );
[ # # ]
[ # # # # ]
[ # # ]
193 [ # # ]: 0 : pDev->Pop();
194 : 0 : }
195 : :
196 : :
197 : 5 : void SpinButton::Paint( const Rectangle& )
198 : : {
199 : 5 : HideFocus();
200 : :
201 : 5 : sal_Bool bEnable = IsEnabled();
202 : : ImplDrawSpinButton( this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn,
203 : 5 : bEnable && ImplIsUpperEnabled(),
204 [ - + ]: 10 : bEnable && ImplIsLowerEnabled(), mbHorz, sal_True );
[ + - + - ]
[ + - ]
205 : :
206 [ - + ]: 5 : if ( HasFocus() )
207 : 0 : ShowFocus( maFocusRect );
208 : 5 : }
209 : :
210 : : // -----------------------------------------------------------------------
211 : :
212 : 0 : void SpinButton::MouseButtonDown( const MouseEvent& rMEvt )
213 : : {
214 [ # # ][ # # ]: 0 : if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
[ # # ]
215 : : {
216 : 0 : mbUpperIn = sal_True;
217 : 0 : mbInitialUp = sal_True;
218 : 0 : Invalidate( maUpperRect );
219 : : }
220 [ # # ][ # # ]: 0 : else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
[ # # ]
221 : : {
222 : 0 : mbLowerIn = sal_True;
223 : 0 : mbInitialDown = sal_True;
224 : 0 : Invalidate( maLowerRect );
225 : : }
226 : :
227 [ # # ][ # # ]: 0 : if ( mbUpperIn || mbLowerIn )
228 : : {
229 : 0 : Update();
230 : 0 : CaptureMouse();
231 [ # # ]: 0 : if ( mbRepeat )
232 : 0 : maRepeatTimer.Start();
233 : : }
234 : 0 : }
235 : :
236 : : // -----------------------------------------------------------------------
237 : :
238 : 0 : void SpinButton::MouseButtonUp( const MouseEvent& )
239 : : {
240 : 0 : ReleaseMouse();
241 [ # # ]: 0 : if ( mbRepeat )
242 : : {
243 : 0 : maRepeatTimer.Stop();
244 : 0 : maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
245 : : }
246 : :
247 [ # # ]: 0 : if ( mbUpperIn )
248 : : {
249 : 0 : mbUpperIn = sal_False;
250 : 0 : Invalidate( maUpperRect );
251 : 0 : Update();
252 : 0 : Up();
253 : : }
254 [ # # ]: 0 : else if ( mbLowerIn )
255 : : {
256 : 0 : mbLowerIn = sal_False;
257 : 0 : Invalidate( maLowerRect );
258 : 0 : Update();
259 : 0 : Down();
260 : : }
261 : :
262 : 0 : mbInitialUp = mbInitialDown = sal_False;
263 : 0 : }
264 : :
265 : : // -----------------------------------------------------------------------
266 : :
267 : 0 : void SpinButton::MouseMove( const MouseEvent& rMEvt )
268 : : {
269 [ # # ][ # # ]: 0 : if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) )
[ # # ][ # # ]
270 : 0 : return;
271 : :
272 [ # # ][ # # ]: 0 : if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
[ # # ][ # # ]
273 : : mbUpperIn && mbInitialUp )
274 : : {
275 : 0 : mbUpperIn = sal_False;
276 : 0 : maRepeatTimer.Stop();
277 : 0 : Invalidate( maUpperRect );
278 : 0 : Update();
279 : : }
280 [ # # ][ # # ]: 0 : else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
[ # # ]
281 : : mbLowerIn & mbInitialDown )
282 : : {
283 : 0 : mbLowerIn = sal_False;
284 : 0 : maRepeatTimer.Stop();
285 : 0 : Invalidate( maLowerRect );
286 : 0 : Update();
287 : : }
288 [ # # ][ # # ]: 0 : else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
[ # # ][ # # ]
289 : 0 : !mbUpperIn && mbInitialUp )
290 : : {
291 : 0 : mbUpperIn = sal_True;
292 [ # # ]: 0 : if ( mbRepeat )
293 : 0 : maRepeatTimer.Start();
294 : 0 : Invalidate( maUpperRect );
295 : 0 : Update();
296 : : }
297 [ # # ][ # # ]: 0 : else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
[ # # ][ # # ]
298 : 0 : !mbLowerIn && mbInitialDown )
299 : : {
300 : 0 : mbLowerIn = sal_True;
301 [ # # ]: 0 : if ( mbRepeat )
302 : 0 : maRepeatTimer.Start();
303 : 0 : Invalidate( maLowerRect );
304 : 0 : Update();
305 : : }
306 : : }
307 : :
308 : : // -----------------------------------------------------------------------
309 : :
310 : 0 : void SpinButton::KeyInput( const KeyEvent& rKEvt )
311 : : {
312 [ # # ]: 0 : if ( !rKEvt.GetKeyCode().GetModifier() )
313 : : {
314 [ # # # # ]: 0 : switch ( rKEvt.GetKeyCode().GetCode() )
315 : : {
316 : : case KEY_LEFT:
317 : : case KEY_RIGHT:
318 : : {
319 : 0 : sal_Bool bUp = KEY_RIGHT == rKEvt.GetKeyCode().GetCode();
320 [ # # ][ # # ]: 0 : if ( mbHorz && !ImplMoveFocus( bUp ) )
[ # # ]
321 [ # # ]: 0 : bUp ? Up() : Down();
322 : : }
323 : 0 : break;
324 : :
325 : : case KEY_UP:
326 : : case KEY_DOWN:
327 : : {
328 : 0 : sal_Bool bUp = KEY_UP == rKEvt.GetKeyCode().GetCode();
329 [ # # ][ # # ]: 0 : if ( !mbHorz && !ImplMoveFocus( KEY_UP == rKEvt.GetKeyCode().GetCode() ) )
[ # # ]
330 [ # # ]: 0 : bUp ? Up() : Down();
331 : : }
332 : 0 : break;
333 : :
334 : : case KEY_SPACE:
335 [ # # ]: 0 : mbUpperIsFocused ? Up() : Down();
336 : 0 : break;
337 : :
338 : : default:
339 : 0 : Control::KeyInput( rKEvt );
340 : 0 : break;
341 : : }
342 : : }
343 : : else
344 : 0 : Control::KeyInput( rKEvt );
345 : 0 : }
346 : :
347 : : // -----------------------------------------------------------------------
348 : :
349 : 24 : void SpinButton::StateChanged( StateChangedType nType )
350 : : {
351 [ - + + ]: 24 : switch ( nType )
352 : : {
353 : : case STATE_CHANGE_DATA:
354 : : case STATE_CHANGE_ENABLE:
355 : 0 : Invalidate();
356 : 0 : break;
357 : :
358 : : case STATE_CHANGE_STYLE:
359 : : {
360 : 4 : sal_Bool bNewRepeat = 0 != ( GetStyle() & WB_REPEAT );
361 [ + + ]: 4 : if ( bNewRepeat != mbRepeat )
362 : : {
363 [ - + ]: 2 : if ( maRepeatTimer.IsActive() )
364 : : {
365 : 0 : maRepeatTimer.Stop();
366 : 0 : maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
367 : : }
368 : 2 : mbRepeat = bNewRepeat;
369 : : }
370 : :
371 : 4 : sal_Bool bNewHorz = 0 != ( GetStyle() & WB_HSCROLL );
372 [ + + ]: 4 : if ( bNewHorz != mbHorz )
373 : : {
374 : 2 : mbHorz = bNewHorz;
375 : 2 : Resize();
376 : : }
377 : : }
378 : 4 : break;
379 : : }
380 : :
381 : 24 : Control::StateChanged( nType );
382 : 24 : }
383 : :
384 : : // -----------------------------------------------------------------------
385 : :
386 : 2 : void SpinButton::SetRangeMin( long nNewRange )
387 : : {
388 [ + - ]: 2 : SetRange( Range( nNewRange, GetRangeMax() ) );
389 : 2 : }
390 : :
391 : : // -----------------------------------------------------------------------
392 : :
393 : 2 : void SpinButton::SetRangeMax( long nNewRange )
394 : : {
395 [ + - ]: 2 : SetRange( Range( GetRangeMin(), nNewRange ) );
396 : 2 : }
397 : :
398 : : // -----------------------------------------------------------------------
399 : :
400 : 4 : void SpinButton::SetRange( const Range& rRange )
401 : : {
402 : : // adjust rage
403 : 4 : Range aRange = rRange;
404 : 4 : aRange.Justify();
405 : 4 : long nNewMinRange = aRange.Min();
406 : 4 : long nNewMaxRange = aRange.Max();
407 : :
408 : : // do something only if old and new range differ
409 [ - + ][ + - ]: 4 : if ( (mnMinRange != nNewMinRange) ||
410 : : (mnMaxRange != nNewMaxRange) )
411 : : {
412 : 0 : mnMinRange = nNewMinRange;
413 : 0 : mnMaxRange = nNewMaxRange;
414 : :
415 : : // adjust value to new range, if necessary
416 [ # # ]: 0 : if ( mnValue > mnMaxRange )
417 : 0 : mnValue = mnMaxRange;
418 [ # # ]: 0 : if ( mnValue < mnMinRange )
419 : 0 : mnValue = mnMinRange;
420 : :
421 [ # # ]: 0 : StateChanged( STATE_CHANGE_DATA );
422 : : }
423 : 4 : }
424 : :
425 : : // -----------------------------------------------------------------------
426 : :
427 : 2 : void SpinButton::SetValue( long nValue )
428 : : {
429 : : // adjust, if necessary
430 [ - + ]: 2 : if ( nValue > mnMaxRange )
431 : 0 : nValue = mnMaxRange;
432 [ - + ]: 2 : if ( nValue < mnMinRange )
433 : 0 : nValue = mnMinRange;
434 : :
435 [ - + ]: 2 : if ( mnValue != nValue )
436 : : {
437 : 0 : mnValue = nValue;
438 : 0 : StateChanged( STATE_CHANGE_DATA );
439 : : }
440 : 2 : }
441 : :
442 : : // -----------------------------------------------------------------------
443 : :
444 : 0 : void SpinButton::GetFocus()
445 : : {
446 : 0 : ShowFocus( maFocusRect );
447 : 0 : Control::GetFocus();
448 : 0 : }
449 : :
450 : : // -----------------------------------------------------------------------
451 : :
452 : 0 : void SpinButton::LoseFocus()
453 : : {
454 : 0 : HideFocus();
455 : 0 : Control::LoseFocus();
456 : 0 : }
457 : :
458 : : // -----------------------------------------------------------------------
459 : :
460 : 0 : sal_Bool SpinButton::ImplMoveFocus( sal_Bool _bUpper )
461 : : {
462 [ # # ]: 0 : if ( _bUpper == mbUpperIsFocused )
463 : 0 : return sal_False;
464 : :
465 : 0 : HideFocus();
466 : 0 : ImplCalcFocusRect( _bUpper );
467 [ # # ]: 0 : if ( HasFocus() )
468 : 0 : ShowFocus( maFocusRect );
469 : 0 : return sal_True;
470 : : }
471 : :
472 : : // -----------------------------------------------------------------------
473 : :
474 : 6 : void SpinButton::ImplCalcFocusRect( sal_Bool _bUpper )
475 : : {
476 [ + - ]: 6 : maFocusRect = _bUpper ? maUpperRect : maLowerRect;
477 : : // inflate by some pixels
478 : 6 : maFocusRect.Left() += 2;
479 : 6 : maFocusRect.Top() += 2;
480 : 6 : maFocusRect.Right() -= 2;
481 : 6 : maFocusRect.Bottom() -= 2;
482 : 6 : mbUpperIsFocused = _bUpper;
483 : 6 : }
484 : :
485 : : // -----------------------------------------------------------------------
486 : :
487 : 0 : Rectangle* SpinButton::ImplFindPartRect( const Point& rPt )
488 : : {
489 [ # # ]: 0 : if( maUpperRect.IsInside( rPt ) )
490 : 0 : return &maUpperRect;
491 [ # # ]: 0 : else if( maLowerRect.IsInside( rPt ) )
492 : 0 : return &maLowerRect;
493 : : else
494 : 0 : return NULL;
495 : : }
496 : :
497 : 0 : long SpinButton::PreNotify( NotifyEvent& rNEvt )
498 : : {
499 : 0 : long nDone = 0;
500 : 0 : const MouseEvent* pMouseEvt = NULL;
501 : :
502 [ # # ][ # # ]: 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
[ # # ]
503 : : {
504 [ # # ][ # # ]: 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
[ # # ][ # # ]
505 : : {
506 : : // trigger redraw if mouse over state has changed
507 [ # # # # ]: 0 : if( IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) ||
[ # # ]
508 : 0 : IsNativeControlSupported(CTRL_SPINBOX, PART_ALL_BUTTONS) )
509 : : {
510 [ # # ]: 0 : Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
511 [ # # ]: 0 : Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
512 [ # # ][ # # ]: 0 : if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
[ # # ][ # # ]
513 : : {
514 [ # # ]: 0 : Region aRgn( GetActiveClipRegion() );
515 [ # # ]: 0 : if( pLastRect )
516 : : {
517 [ # # ][ # # ]: 0 : SetClipRegion( *pLastRect );
[ # # ]
518 [ # # ]: 0 : Paint( *pLastRect );
519 [ # # ]: 0 : SetClipRegion( aRgn );
520 : : }
521 [ # # ]: 0 : if( pRect )
522 : : {
523 [ # # ][ # # ]: 0 : SetClipRegion( *pRect );
[ # # ]
524 [ # # ]: 0 : Paint( *pRect );
525 [ # # ]: 0 : SetClipRegion( aRgn );
526 [ # # ]: 0 : }
527 : : }
528 : : }
529 : : }
530 : : }
531 : :
532 [ # # ]: 0 : return nDone ? nDone : Control::PreNotify(rNEvt);
533 : : }
534 : :
535 : : // -----------------------------------------------------------------------
536 : :
537 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|