KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > patterns > thickclient > application > swt > CharacterPad


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: CharacterPad.java,v 1.6 2007/01/07 06:14:15 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.patterns.thickclient.application.swt;
23
24 import java.util.Date JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionAdapter;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.events.SelectionListener;
33 import org.eclipse.swt.graphics.Point;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Canvas;
38 import org.eclipse.swt.widgets.Composite;
39 import org.eclipse.swt.widgets.Label;
40 import org.eclipse.swt.widgets.Text;
41 import org.opensubsystems.core.application.swt.ResourceManager;
42 import org.opensubsystems.core.util.GlobalConstants;
43 import org.opensubsystems.patterns.thickclient.application.EventProcessor;
44 import org.opensubsystems.patterns.thickclient.application.ModificationListener;
45 import org.opensubsystems.patterns.thickclient.application.TextProcessor;
46
47 /**
48  * Control which allows user to type characters using mouse or finger on a screen.
49  *
50  * @version $Id: CharacterPad.java,v 1.6 2007/01/07 06:14:15 bastafidli Exp $
51  * @author Martin Cerba
52  * @code.reviewer Miro Halas
53  * @code.reviewed 1.4 2006/04/05 05:31:04 bastafidli
54  */

55 public class CharacterPad extends Canvas
56                           implements ModificationListener,
57                                      TextProcessor,
58                                      EventProcessor
59 {
60    // Constants ////////////////////////////////////////////////////////////////
61

62    /**
63     * Base (smallest) dialog height constant.
64     */

65    protected static final int BASE_DIALOG_HEIGHT = 200;
66       
67    /**
68     * special flag for character pad
69     */

70    public static final int CHP_NONE = 0;
71
72    /**
73     * set caps lock to uppercase on beginnig
74     */

75    public static final int CHP_UPPERCASE = 1;
76
77    /**
78     * hide caps lock button
79     */

80    public static final int CHP_HIDECAPSLOCK = 2;
81
82    /**
83     * if CHP_UPPERCASE switch to loweracse after first chracter
84     */

85    public static final int CHP_SWITCHTOLOWERCASE = 4;
86
87    /**
88     * constant for all numeric characters
89     */

90    public static final CharacterPadLayout KEY_LAYOUT_123
91                            = new CharacterPadLayout(
92                                      "1234567890",
93                                      10);
94
95
96    /**
97     * constant for all numeric characters
98     */

99    public static final CharacterPadLayout KEY_LAYOUT_123_QWERTY
100                            = new CharacterPadLayout(
101                                      "1234567890" +
102                                      "QWERTYUIOP" +
103                                      "ASDFGHJKL " +
104                                      " ZXCVBNM ",
105                                      10);
106
107    /**
108     * constant for all numeric characters
109     */

110    public static final CharacterPadLayout KEY_LAYOUT_QWERTY
111                            = new CharacterPadLayout(
112                                      "QWERTYUIOP" +
113                                      "ASDFGHJKL " +
114                                      " ZXCVBNM ",
115                                      10);
116
117    /**
118     * constant for all numeric characters
119     */

120    public static final CharacterPadLayout KEY_LAYOUT_123_QWERTY_SPECIAL
121                            = new CharacterPadLayout(
122                                      "1234567890-" +
123                                      "QWERTYUIOP " +
124                                      "ASDFGHJKL;\"" +
125                                      " ZXCVBNM,./",
126                                      11);
127
128    /**
129     * Button used to enter values
130     */

131    public static final String JavaDoc[] ENTER_BUTTON = {"Enter"};
132    
133    /**
134     * Width of capslock button
135     */

136    public static final int CAPSLOCK_WIDTH = 2;
137    
138    // Inner classes ////////////////////////////////////////////////////////////
139

140    /**
141     * Structure defining what keys should appear in the keyboard pad and what
142     * is the width of the pad.
143     *
144     * @author Miro Halas
145     */

146    public static class CharacterPadLayout
147    {
148       // Attributes ////////////////////////////////////////////////////////////
149

150       /**
151        * String of characters defining the keys to display.
152        */

153       protected String JavaDoc m_strKeyLayout;
154       
155       /**
156        * How many buttons to display at one line
157        */

158       protected int m_iWidth;
159
160       // Constructors //////////////////////////////////////////////////////////
161

162       /**
163        * @param strKeyLayout - String of characters defining the keys to display.
164        * @param width - how many buttons to display at one line
165        */

166       public CharacterPadLayout(
167          String JavaDoc strKeyLayout,
168          int width
169       )
170       {
171          super();
172          m_strKeyLayout = strKeyLayout;
173          m_iWidth = width;
174       }
175       
176       // Accessors /////////////////////////////////////////////////////////////
177

178       /**
179        * @return int
180        */

181       public int getWidth()
182       {
183          return m_iWidth;
184       }
185       
186       /**
187        * @return String - how many buttons to display at one line
188        */

189       public String JavaDoc getKeyLayout()
190       {
191          return m_strKeyLayout;
192       }
193    }
194
195    // Attributes ///////////////////////////////////////////////////////////////
196

197    /**
198     * Preferred size of this control based on the specified parameters.
199     */

200    protected Point m_preferredSize;
201
202    /**
203     * Set where all listeners listening to the event notifications specific
204     * to this object are stored.
205     */

206    protected Set JavaDoc m_setListeners = new HashSet JavaDoc();
207
208    /**
209     * Field which collects typed characters.
210     */

211    protected Text m_text;
212
213    /**
214     * Date when the content was last modified.
215     * TODO: Improve: Shouldn't this be timestamp?
216     */

217    protected Date JavaDoc m_lastModified;
218
219    /**
220     * Should we hide the capslock flag?
221     */

222    protected boolean m_bHideCapsLock = false;
223    
224    /**
225     * Switch to lower case after characeter will be entered
226     */

227    protected boolean m_bToLowercase = false;
228
229    /**
230     * Initial text for CharacterPad
231     */

232    protected String JavaDoc m_initialText = null;
233
234    /**
235     * Variable for special flags
236     */

237    protected int m_specialFlags = CHP_NONE;
238
239    /**
240     * Caps lock button
241     */

242    protected Button m_capsLock;
243    
244    // Constructors /////////////////////////////////////////////////////////////
245

246    /**
247     * Constructor.
248     *
249     * @param parent - parent of character pad
250     * @param style - combination of SWT.xxx values
251     * @param specialButtons - array of strings for special action buttons
252     * displayed on the bottom of the dialog
253     * @param keyboardLayout - layout of keys for the keyboard pad, see the
254     * KEY_LAYOUT_XXX constants
255     * @param specialFlags - special styles for character pad, combination of
256     * CHP_XXX values
257     * @param bBigButtons - if true then the buttons will be displayed large
258     * otherwise they will be displayed middle size
259     */

260    public CharacterPad(
261       Composite parent,
262       int style,
263       String JavaDoc[] specialButtons,
264       CharacterPadLayout keyboardLayout,
265       int specialFlags,
266       boolean bBigButtons
267    )
268    {
269       super(parent, style);
270
271       m_specialFlags = specialFlags;
272
273       if ((m_specialFlags & CHP_HIDECAPSLOCK) == CHP_HIDECAPSLOCK)
274       {
275          m_bHideCapsLock = true;
276       }
277       
278       if ((m_specialFlags & CHP_SWITCHTOLOWERCASE) == CHP_SWITCHTOLOWERCASE)
279       {
280          m_bToLowercase = true;
281       }
282       
283       int iDialogLineHeight;
284       
285       if (bBigButtons)
286       {
287          iDialogLineHeight = (int)(ResourceManager.BIG_BUTTON_FONT_HEIGHT * 1.8);
288       }
289       else
290       {
291          iDialogLineHeight = (int)(ResourceManager.MIDDLE_BUTTON_FONT_HEIGHT * 2.3);
292       }
293       
294       int dialogHeigth = BASE_DIALOG_HEIGHT;
295       if ((specialButtons != null) && (specialButtons.length > 0))
296       {
297          dialogHeigth += iDialogLineHeight;
298       }
299       if ((keyboardLayout != null) && (keyboardLayout.getKeyLayout().length() > 0))
300       {
301          // one line for every X special chars
302
dialogHeigth += iDialogLineHeight
303                          * (((keyboardLayout.getKeyLayout().length()
304                             / keyboardLayout.getWidth()) + 1));
305       }
306       m_preferredSize = new Point(keyboardLayout.getWidth() * iDialogLineHeight * 2,
307                                   dialogHeigth);
308       
309       GridLayout layout = new GridLayout();
310       layout.numColumns = keyboardLayout.getWidth();
311       layout.marginHeight = 0;
312       layout.marginWidth = 0;
313       layout.makeColumnsEqualWidth = true;
314
315       setLayout(layout);
316       
317       GridData textData;
318
319       m_text = new Text(this, SWT.BORDER);
320       ResourceManager.getInstance().setBigTextFont(m_text);
321
322       textData = new GridData();
323       textData.horizontalSpan = keyboardLayout.getWidth();
324       textData.horizontalAlignment = GridData.FILL;
325       textData.verticalAlignment = GridData.FILL;
326       // Expand horizontally if more space becomes available
327
textData.grabExcessHorizontalSpace = true;
328       m_text.setLayoutData(textData);
329       
330       Label emptySpace;
331       GridData emptySpaceData;
332       String JavaDoc specialChars = keyboardLayout.getKeyLayout();
333
334       if ((specialChars != null) && (specialChars.length() > 0))
335       {
336          String JavaDoc actualChar;
337          
338          for (int index = 0; index < specialChars.length(); index++)
339          {
340             actualChar = specialChars.substring(index, index + 1);
341             
342             if (actualChar.equals("&"))
343             {
344                createButton("&&", new TextModificationSelectionAdapter(this,
345                                          this, "&", m_text),
346                             bBigButtons);
347             }
348             else if (actualChar.equals(" ")) // add empty space
349
{
350                emptySpace = new Label(this, SWT.NONE);
351                emptySpace.setText(" ");
352                emptySpaceData = new GridData();
353                emptySpaceData.horizontalSpan = 1;
354                emptySpaceData.horizontalAlignment = GridData.FILL;
355                emptySpaceData.verticalAlignment = GridData.FILL;
356                emptySpaceData.grabExcessVerticalSpace = true;
357                emptySpace.setLayoutData(emptySpaceData);
358             }
359             else
360             {
361                createButton(specialChars.substring(index, index + 1),
362                             new TextModificationSelectionAdapter(this, this,
363                                    actualChar, m_text),
364                             bBigButtons);
365             }
366          }
367
368          emptySpace = new Label(this, SWT.NONE);
369          emptySpace.setText(" ");
370          emptySpaceData = new GridData();
371          emptySpaceData.horizontalSpan = keyboardLayout.getWidth()
372                            - (specialChars.length() % keyboardLayout.getWidth());
373          emptySpaceData.horizontalAlignment = GridData.FILL;
374          emptySpaceData.verticalAlignment = GridData.FILL;
375          emptySpaceData.grabExcessVerticalSpace = true;
376          emptySpace.setLayoutData(emptySpaceData);
377
378          // fill empty space on right of special chars
379
}
380
381       // now we add clear, spacebar, backspace and capslock buttons
382
int iAllocatedSpace;
383       int iSpaceWidth;
384       boolean spaceBarSeparators;
385       
386       iAllocatedSpace = 1 // Clear
387
+ 1; // Clear All
388
if (!m_bHideCapsLock)
389       {
390          iAllocatedSpace += CAPSLOCK_WIDTH;
391       }
392       if ((keyboardLayout.getWidth() - iAllocatedSpace) >= 5)
393       {
394          spaceBarSeparators = true;
395          iSpaceWidth = keyboardLayout.getWidth() - iAllocatedSpace - 2;
396       }
397       else
398       {
399          spaceBarSeparators = false;
400          iSpaceWidth = keyboardLayout.getWidth() - iAllocatedSpace;
401       }
402       
403       GridData capsLockData;
404
405       if (!m_bHideCapsLock)
406       {
407          m_capsLock = new Button(this, SWT.BORDER | SWT.TOGGLE);
408          m_capsLock.setText("Caps lock");
409          m_capsLock.setAlignment(SWT.CENTER);
410          if ((m_specialFlags & CHP_UPPERCASE) == CHP_UPPERCASE)
411          {
412             m_capsLock.setSelection(true);
413             m_bHideCapsLock = true;
414          }
415          
416          if (bBigButtons)
417          {
418             ResourceManager.getInstance().setBigButtonFont(m_capsLock);
419          }
420          else
421          {
422             ResourceManager.getInstance().setMiddleButtonFont(m_capsLock);
423          }
424          capsLockData = new GridData();
425          capsLockData.horizontalSpan = CAPSLOCK_WIDTH;
426          capsLockData.horizontalAlignment = GridData.FILL;
427          capsLockData.verticalAlignment = GridData.FILL;
428          capsLockData.grabExcessVerticalSpace = true;
429          m_capsLock.setLayoutData(capsLockData);
430          m_capsLock.addSelectionListener(new SelectionAdapter()
431          {
432             public void widgetSelected(SelectionEvent event)
433             {
434                if (m_bHideCapsLock)
435                {
436                   m_bHideCapsLock = false;
437                }
438                else
439                {
440                   m_bHideCapsLock = true;
441                }
442                m_text.setFocus();
443             }
444
445             public void widgetDefaultSelected(SelectionEvent event)
446             {
447                // Process it just as regular selection
448
widgetSelected(event);
449             }
450          });
451       }
452
453       Button back;
454       GridData backData;
455
456       back = new Button(this, SWT.BORDER);
457       back.setText("C");
458       if (bBigButtons)
459       {
460          ResourceManager.getInstance().setBigButtonFont(back);
461       }
462       else
463       {
464          ResourceManager.getInstance().setMiddleButtonFont(back);
465       }
466       backData = new GridData();
467       backData.horizontalSpan = 1;
468       backData.horizontalAlignment = GridData.FILL;
469       backData.verticalAlignment = GridData.FILL;
470       backData.grabExcessVerticalSpace = true;
471       back.setLayoutData(backData);
472       back.addSelectionListener(
473          new TextModificationSelectionAdapter(this, this,
474                 TextModificationSelectionAdapter.FUNCTION_CLEAR, m_text));
475
476       if (spaceBarSeparators)
477       {
478          emptySpace = new Label(this, SWT.NONE);
479          emptySpace.setText(" ");
480          emptySpaceData = new GridData();
481          emptySpaceData.horizontalSpan = 1;
482          emptySpaceData.horizontalAlignment = GridData.FILL;
483          emptySpaceData.verticalAlignment = GridData.FILL;
484          emptySpaceData.grabExcessVerticalSpace = true;
485          emptySpace.setLayoutData(emptySpaceData);
486       }
487       
488       Button space;
489       GridData spaceData;
490
491       space = new Button(this, SWT.BORDER);
492       space.setText("Spacebar");
493       if (bBigButtons)
494       {
495          ResourceManager.getInstance().setBigButtonFont(space);
496       }
497       else
498       {
499          ResourceManager.getInstance().setMiddleButtonFont(space);
500       }
501       spaceData = new GridData();
502       spaceData.horizontalSpan = iSpaceWidth;
503       spaceData.horizontalAlignment = GridData.FILL;
504       spaceData.verticalAlignment = GridData.FILL;
505       spaceData.grabExcessVerticalSpace = true;
506       space.setLayoutData(spaceData);
507       space.addSelectionListener(new TextModificationSelectionAdapter(this,
508                                         this, " ", m_text));
509
510       if (spaceBarSeparators)
511       {
512          emptySpace = new Label(this, SWT.NONE);
513          emptySpace.setText(" ");
514          emptySpaceData = new GridData();
515          emptySpaceData.horizontalSpan = 1;
516          emptySpaceData.horizontalAlignment = GridData.FILL;
517          emptySpaceData.verticalAlignment = GridData.FILL;
518          emptySpaceData.grabExcessVerticalSpace = true;
519          emptySpace.setLayoutData(emptySpaceData);
520       }
521
522       Button clear;
523       GridData clearData;
524
525       clear = new Button(this, SWT.BORDER);
526       clear.setText("CA");
527       if (bBigButtons)
528       {
529          ResourceManager.getInstance().setBigButtonFont(clear);
530       }
531       else
532       {
533          ResourceManager.getInstance().setMiddleButtonFont(clear);
534       }
535       clearData = new GridData();
536       clearData.horizontalSpan = 1;
537       clearData.horizontalAlignment = GridData.FILL;
538       clearData.verticalAlignment = GridData.FILL;
539       clearData.grabExcessVerticalSpace = true;
540       clear.setLayoutData(clearData);
541       clear.addSelectionListener(new TextModificationSelectionAdapter(this, this,
542                                         TextModificationSelectionAdapter.FUNCTION_CLEAR_ALL,
543                                         m_text));
544
545       Button specialButton;
546       GridData specialButtonData;
547
548       if (specialButtons != null && specialButtons.length > 0)
549       {
550          int iEmptySpace = keyboardLayout.getWidth() % specialButtons.length;
551          
552          for (int index = 0; index < specialButtons.length; index++)
553          {
554             specialButton = new Button(this, SWT.BORDER);
555             specialButton.setText(specialButtons[index]);
556             specialButton.setAlignment(SWT.CENTER);
557             if (bBigButtons)
558             {
559                ResourceManager.getInstance().setBigButtonFont(specialButton);
560             }
561             else
562             {
563                ResourceManager.getInstance().setMiddleButtonFont(specialButton);
564             }
565             specialButtonData = new GridData();
566             specialButtonData.horizontalSpan = keyboardLayout.getWidth()
567                                                / specialButtons.length;
568             specialButtonData.horizontalAlignment = GridData.FILL;
569             specialButtonData.verticalAlignment = GridData.FILL;
570             specialButtonData.grabExcessVerticalSpace = true;
571             specialButton.setLayoutData(specialButtonData);
572             specialButton.addSelectionListener(
573                new EventNotifierSelectionAdapter(this, specialButtons[index],
574                                                  new Integer JavaDoc(index)));
575
576             if (iEmptySpace > 0) // add empty space behind button
577
{
578                iEmptySpace--;
579                emptySpace = new Label(this, SWT.NONE);
580                emptySpace.setText(" ");
581                emptySpaceData = new GridData();
582                emptySpaceData.horizontalSpan = 1;
583                emptySpaceData.horizontalAlignment = GridData.FILL;
584                emptySpaceData.verticalAlignment = GridData.FILL;
585                emptySpaceData.grabExcessVerticalSpace = true;
586                emptySpace.setLayoutData(emptySpaceData);
587             }
588          }
589       }
590
591       if (m_initialText != null)
592       {
593          m_text.setText(m_initialText);
594       }
595       m_text.setFocus();
596    }
597
598    // Public methods ///////////////////////////////////////////////////////////
599

600    /**
601     * Get preferred size of this control based on the specified parameters.
602     *
603     * @return Point
604     */

605    public Point getPreferredSize()
606    {
607       return m_preferredSize;
608    }
609
610    /**
611     * {@inheritDoc}
612     */

613    public void modified(
614    )
615    {
616       // Remember date of last modification
617
m_lastModified = new Date JavaDoc();
618    }
619
620    /**
621     * {@inheritDoc}
622     */

623    public String JavaDoc processText(
624       String JavaDoc text
625    )
626    {
627       if (m_bHideCapsLock)
628       {
629          text = text.toUpperCase();
630       }
631       else
632       {
633          text = text.toLowerCase();
634       }
635       if (m_bToLowercase)
636       {
637          // switch to lowercase
638
m_bHideCapsLock = false;
639          m_bToLowercase = false;
640          m_capsLock.setSelection(false);
641       }
642       return text;
643    }
644    
645    /**
646     * This function sets maximal nuber of characters typed
647     *
648     * @param iLimit - maximal number of chracters
649     * @return boolean - sucess flag
650     */

651    public boolean setTextLimit(
652       int iLimit
653    )
654    {
655       boolean bReturn = false;
656       
657       if (m_text != null)
658       {
659          m_text.setTextLimit(iLimit);
660          bReturn = true;
661       }
662       
663       return bReturn;
664    }
665
666    /**
667     * {@inheritDoc}
668     */

669    public void processEvent(
670       String JavaDoc strEventName,
671       Integer JavaDoc intEventId
672    )
673    {
674       notifyCharacterPadListeners(intEventId.intValue(), strEventName);
675       modified();
676    }
677
678    /**
679     * Add listener for this character pad.
680     *
681     * @param listener - listener to add
682     */

683    public void addCharacterPadListener(
684       CharacterPadListener listener
685    )
686    {
687       m_setListeners.add(listener);
688    }
689
690    /**
691     * Remove listener from this character pad.
692     *
693     * @param listener - listener to remove
694     */

695    public void removeCharacterPadListener(
696       CharacterPadListener listener
697    )
698    {
699       m_setListeners.remove(listener);
700    }
701
702    /**
703     * Get text from CharacterPad.
704     *
705     * @return String
706     */

707    public String JavaDoc getText()
708    {
709       if (m_text != null)
710       {
711          return m_text.getText();
712       }
713       return null;
714    }
715
716    /**
717     * Set initial text in the CharacterPad
718     *
719     * @param initialText - text for CharacterPad
720     */

721    public void setInitialText(
722       String JavaDoc initialText
723    )
724    {
725       m_initialText = initialText;
726       if (initialText != null)
727       {
728          if (GlobalConstants.ERROR_CHECKING)
729          {
730             assert m_text != null : "text control not created";
731          }
732          
733          m_text.setText(initialText);
734          m_text.setSelection(initialText.length(), initialText.length());
735          m_text.setFocus();
736       }
737    }
738
739    // Helper methods ///////////////////////////////////////////////////////////
740

741    /**
742     * Create new button for this character pad.
743     *
744     * @param strText - text to display on the button
745     * @param listener - listener processing events from the button
746     * @param bBigButtons - if true then the buttons will be displayed large
747     * otherwise they will be displayed middle size
748     */

749    protected void createButton(
750       String JavaDoc strText,
751       SelectionListener listener,
752       boolean bBigButtons
753    )
754    {
755       Button letter;
756       GridData letterData;
757
758       letter = new Button(this, SWT.BORDER);
759       letter.setText(strText);
760       if (bBigButtons)
761       {
762          ResourceManager.getInstance().setBigButtonFont(letter);
763       }
764       else
765       {
766          ResourceManager.getInstance().setMiddleButtonFont(letter);
767       }
768       letterData = new GridData();
769       letterData.horizontalAlignment = GridData.FILL;
770       letterData.verticalAlignment = GridData.FILL;
771       // Expand vertically if more space becomes available
772
letterData.grabExcessVerticalSpace = true;
773       letter.setLayoutData(letterData);
774       letter.addSelectionListener(listener);
775    }
776
777
778    /**
779     * Notify all listeners about event.
780     *
781     * @param intValue - int offset of special button text in original String[]
782     * @param strEvent - button text
783     * @return boolen - if true dialog will by closed
784     */

785    protected boolean notifyCharacterPadListeners(
786       int intValue,
787       String JavaDoc strEvent
788    )
789    {
790       boolean bRetval = false;
791       if ((strEvent == null) || (strEvent.length() == 0))
792       {
793          strEvent = "";
794       }
795       for (Iterator JavaDoc items = m_setListeners.iterator(); items.hasNext();)
796       {
797          bRetval = ((CharacterPadListener)items.next()).takeAction(
798                        this, intValue, strEvent, getText()) || bRetval;
799       }
800       return bRetval;
801    }
802 }
803
Popular Tags