Applied patch [ 600500 ] Tip-of-day: comments, translatable
By Robert O'Connor This is a patch to wxTip Provider classes used by the "Tip of the day" dialog. See wx-dev archives August 2002 for discussion of the functionality design. It does 5 things: -Support for comments inside the tips file. The pound character (#) is used, as recommended by Vadim. -Allows optional easy translation support to tips, by marking them as translatable for gettext, by enclosing them in a _(""). Program will translate these tips at runtime from the active catalog. -Blank lines or lines with just spaces are automatically skipped (I had to put this in, I keep wondering why I get blank tips sometimes and it is because the text file had a empty blank line at the end of the text file). -There is a pluggable virtual function to preprocess to modify the tip in a derived class, in case something specialized is desired, such as variable expansion, etc, as recommended by Julian and Vadim. -Now resets the tip counter if the previous tip is past the end of the file (ie you removed some tips, or changed tip files), as discussed on wx-dev. This patch updates: -The classes. -The class documentation and the Tip-of-the-day topic overview documentation. -The dialogs example, placing some new strings for the tips.txt file which demonstrate how to use the Tip-of-the-day features for in practice. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16887 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -38,15 +38,24 @@ Constructor.
|
|||||||
Return the text of the current tip and pass to the next one. This function is
|
Return the text of the current tip and pass to the next one. This function is
|
||||||
pure virtual, it should be implemented in the derived classes.
|
pure virtual, it should be implemented in the derived classes.
|
||||||
|
|
||||||
|
\membersection{wxTipProvider::PreprocessTip}\label{wxtipproviderpreprocesstip}
|
||||||
|
\funct{virtual wxString}{PreProcessTip}{\param{const wxString\&} {tip}}
|
||||||
|
|
||||||
|
Returns a modified tip. This function will be called immediately after read,
|
||||||
|
and before being check whether it is a comment, an empty string or a string
|
||||||
|
to translate. You can optionally override this in your custom user-derived class
|
||||||
|
to optionally to modify the tip as soon as it is read. You can return any
|
||||||
|
modification to the string. If you return wxEmptyString, then this tip is
|
||||||
|
skipped, and the next one is read.
|
||||||
|
|
||||||
\membersection{wxCurrentTipProvider::GetCurrentTip}\label{wxtipprovidergetcurrenttip}
|
\membersection{wxCurrentTipProvider::GetCurrentTip}\label{wxtipprovidergetcurrenttip}
|
||||||
|
|
||||||
\constfunc{size\_t}{GetCurrentTip}{\void}
|
\constfunc{size\_t}{GetCurrentTip}{\void}
|
||||||
|
|
||||||
Returns the index of the current tip (i.e. the one which would be returned by
|
Returns the index of the current tip (i.e. the one which would be returned by
|
||||||
GetTip).
|
GetTip).
|
||||||
|
|
||||||
The program usually remembers the value returned by this function after calling
|
The program usually remembers the value returned by this function after calling
|
||||||
\helpref{wxShowTip}{wxshowtip}. Note that it is not the same as the value which
|
\helpref{wxShowTip}{wxshowtip}. Note that it is not the same as the value which
|
||||||
was passed to wxShowTip $+ 1$ because the user might have pressed the "Next"
|
was passed to wxShowTip $+ 1$ because the user might have pressed the "Next"
|
||||||
button in the tip dialog.
|
button in the tip dialog.
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ hardcode the tips inside your program), you just have to derive another class
|
|||||||
from wxTipProvider and pass a pointer to the object of this class to wxShowTip
|
from wxTipProvider and pass a pointer to the object of this class to wxShowTip
|
||||||
- then you don't need wxCreateFileTipProvider at all.
|
- then you don't need wxCreateFileTipProvider at all.
|
||||||
|
|
||||||
Finally, you will probably want to save somewhere the index of the tip last
|
You will probably want to save somewhere the index of the tip last
|
||||||
shown - so that the program doesn't always show the same tip on startup. As you
|
shown - so that the program doesn't always show the same tip on startup. As you
|
||||||
also need to remember whether to show tips or not (you shouldn't do it if the
|
also need to remember whether to show tips or not (you shouldn't do it if the
|
||||||
user unchecked "Show tips on startup" checkbox in the dialog), you will
|
user unchecked "Show tips on startup" checkbox in the dialog), you will
|
||||||
@@ -41,3 +41,26 @@ last shown tip (as returned by
|
|||||||
\helpref{wxTipProvider::GetCurrentTip}{wxtipprovidergetcurrenttip} and the flag
|
\helpref{wxTipProvider::GetCurrentTip}{wxtipprovidergetcurrenttip} and the flag
|
||||||
telling whether to show the tips at startup at all.
|
telling whether to show the tips at startup at all.
|
||||||
|
|
||||||
|
In a tips.txt file, lines that begin with a \# character are considered comments
|
||||||
|
and are automatically skipped. Blank lines and lines only having spaces are also
|
||||||
|
skipped.
|
||||||
|
|
||||||
|
You can easily add runtime-translation capacity by placing each line of the
|
||||||
|
tips.txt file inside the usual translation macro. For example, your tips.txt
|
||||||
|
file would look like this:
|
||||||
|
\begin{verbatim}
|
||||||
|
_("This is my first tip")
|
||||||
|
_("This is my second tip")
|
||||||
|
\end{verbatim}
|
||||||
|
Now add your tips.txt file into the list of files that gettext searches
|
||||||
|
for translatable strings. The tips will thus get included into your
|
||||||
|
generated .po file catalog and be translated at runtime along with the rest of
|
||||||
|
your aplication's translatable strings.
|
||||||
|
Note1: Each line in the tips.txt file needs to strictly begin with exactly the
|
||||||
|
3 characters of underscore-parenthesis-doublequote, and end with
|
||||||
|
doublequote-parenthesis, as shown above.
|
||||||
|
Note2: Remember to escape any doublequote characters within the tip string with
|
||||||
|
a backslash-doublequote.
|
||||||
|
|
||||||
|
See the dialogs program in your samples folder for a working example inside a
|
||||||
|
program.
|
||||||
|
@@ -10,6 +10,9 @@ Most C++ compilers cannot compile the WINE sources yet (this includes
|
|||||||
all versions of g++ and egcs) so you have to make a minimal change
|
all versions of g++ and egcs) so you have to make a minimal change
|
||||||
and recompile all of WINE in order to get anywhere.
|
and recompile all of WINE in order to get anywhere.
|
||||||
|
|
||||||
|
(Note: this information may be out of date now. See notes at
|
||||||
|
the bottom of this file.)
|
||||||
|
|
||||||
This change has do be applied to the /include/windef.h file, line 59
|
This change has do be applied to the /include/windef.h file, line 59
|
||||||
in the section "Calling convention definitions", where the sources
|
in the section "Calling convention definitions", where the sources
|
||||||
reads:
|
reads:
|
||||||
@@ -153,18 +156,18 @@ You can get the newest version of the WINE from the WINE homepage at:
|
|||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
./configure options
|
./configure options
|
||||||
|
|
||||||
If you want to use system's C and C++ compiler,
|
If you want to use system's C and C++ compiler,
|
||||||
set environment variables CC and CCC as
|
set environment variables CC and CCC as
|
||||||
|
|
||||||
% setenv CC cc
|
% setenv CC cc
|
||||||
% setenv CCC CC
|
% setenv CCC CC
|
||||||
% ./configure options
|
% ./configure options
|
||||||
|
|
||||||
to see all the options please use:
|
to see all the options please use:
|
||||||
|
|
||||||
./configure --help
|
./configure --help
|
||||||
|
|
||||||
The basic philosophy is that if you want to use different
|
The basic philosophy is that if you want to use different
|
||||||
configurations, like a debug and a release version,
|
configurations, like a debug and a release version,
|
||||||
@@ -192,52 +195,52 @@ in wxWindows snapshot 6, but not yet all (ODBC not).
|
|||||||
|
|
||||||
You must do this by running configure with either of:
|
You must do this by running configure with either of:
|
||||||
|
|
||||||
--with-wine Use the WINE library
|
--with-wine Use the WINE library
|
||||||
|
|
||||||
The following options handle the kind of library you want to build.
|
The following options handle the kind of library you want to build.
|
||||||
|
|
||||||
--enable-threads Compile without thread support. Threads
|
--enable-threads Compile with thread support. Threads
|
||||||
support is also required for the
|
support is also required for the
|
||||||
socket code to work.
|
socket code to work.
|
||||||
|
|
||||||
--disable-shared Do not create shared libraries.
|
--disable-shared Do not create shared libraries.
|
||||||
|
|
||||||
--disable-optimise Do not optimise the code. Can
|
--disable-optimise Do not optimise the code. Can
|
||||||
sometimes be useful for debugging
|
sometimes be useful for debugging
|
||||||
and is required on some architectures
|
and is required on some architectures
|
||||||
such as Sun with gcc 2.8.X which
|
such as Sun with gcc 2.8.X which
|
||||||
would otherwise produce segvs.
|
would otherwise produce segvs.
|
||||||
|
|
||||||
--enable-profile Add profiling info to the object
|
--enable-profile Add profiling info to the object
|
||||||
files. Currently broken, I think.
|
files. Currently broken, I think.
|
||||||
|
|
||||||
--enable-no_rtti Enable compilation without creation of
|
--enable-no_rtti Enable compilation without creation of
|
||||||
C++ RTTI information in object files.
|
C++ RTTI information in object files.
|
||||||
This will speed-up compilation and reduce
|
This will speed-up compilation and reduce
|
||||||
binary size.
|
binary size.
|
||||||
|
|
||||||
--enable-no_exceptions Enable compilation without creation of
|
--enable-no_exceptions Enable compilation without creation of
|
||||||
C++ exception information in object files.
|
C++ exception information in object files.
|
||||||
This will speed-up compilation and reduce
|
This will speed-up compilation and reduce
|
||||||
binary size. Also fewer crashes during the
|
binary size. Also fewer crashes during the
|
||||||
actual compilation...
|
actual compilation...
|
||||||
|
|
||||||
--enable-mem_tracing Add built-in memory tracing.
|
--enable-mem_tracing Add built-in memory tracing.
|
||||||
|
|
||||||
--enable-dmalloc Use the dmalloc memory debugger.
|
--enable-dmalloc Use the dmalloc memory debugger.
|
||||||
Read more at www.letters.com/dmalloc/
|
Read more at www.letters.com/dmalloc/
|
||||||
|
|
||||||
--enable-debug_info Add debug info to object files and
|
--enable-debug_info Add debug info to object files and
|
||||||
executables for use with debuggers
|
executables for use with debuggers
|
||||||
such as gdb (or its many frontends).
|
such as gdb (or its many frontends).
|
||||||
|
|
||||||
--enable-debug_flag Define __DEBUG__ and __WXDEBUG__ when
|
--enable-debug_flag Define __DEBUG__ and __WXDEBUG__ when
|
||||||
compiling. This enable wxWindows' very
|
compiling. This enable wxWindows' very
|
||||||
useful internal debugging tricks (such
|
useful internal debugging tricks (such
|
||||||
as automatically reporting illegal calls)
|
as automatically reporting illegal calls)
|
||||||
to work. Note that program and library
|
to work. Note that program and library
|
||||||
must be compiled with the same debug
|
must be compiled with the same debug
|
||||||
options.
|
options.
|
||||||
|
|
||||||
* Feature Options
|
* Feature Options
|
||||||
-------------------
|
-------------------
|
||||||
@@ -251,38 +254,38 @@ drastically reduced by removing features from wxWindows that
|
|||||||
are not used in your program. The most relevant such features
|
are not used in your program. The most relevant such features
|
||||||
are
|
are
|
||||||
|
|
||||||
--without-libpng Disables PNG image format code.
|
--without-libpng Disables PNG image format code.
|
||||||
|
|
||||||
--without-libjpeg Disables JPEG image format code.
|
--without-libjpeg Disables JPEG image format code.
|
||||||
|
|
||||||
{ --without-odbc Disables ODBC code. Not yet. }
|
{ --without-odbc Disables ODBC code. Not yet. }
|
||||||
|
|
||||||
--disable-resources Disables the use of *.wxr type
|
--disable-resources Disables the use of *.wxr type
|
||||||
resources.
|
resources.
|
||||||
|
|
||||||
--disable-threads Disables threads. Will also
|
--disable-threads Disables threads. Will also
|
||||||
disable sockets.
|
disable sockets.
|
||||||
|
|
||||||
--disable-sockets Disables sockets.
|
--disable-sockets Disables sockets.
|
||||||
|
|
||||||
--disable-dnd Disables Drag'n'Drop.
|
--disable-dnd Disables Drag'n'Drop.
|
||||||
|
|
||||||
--disable-clipboard Disables Clipboard.
|
--disable-clipboard Disables Clipboard.
|
||||||
|
|
||||||
--disable-serial Disables object instance serialisation.
|
--disable-serial Disables object instance serialisation.
|
||||||
|
|
||||||
--disable-streams Disables the wxStream classes.
|
--disable-streams Disables the wxStream classes.
|
||||||
|
|
||||||
--disable-file Disables the wxFile class.
|
--disable-file Disables the wxFile class.
|
||||||
|
|
||||||
--disable-textfile Disables the wxTextFile class.
|
--disable-textfile Disables the wxTextFile class.
|
||||||
|
|
||||||
--disable-intl Disables the internationalisation.
|
--disable-intl Disables the internationalisation.
|
||||||
|
|
||||||
--disable-validators Disables validators.
|
--disable-validators Disables validators.
|
||||||
|
|
||||||
--disable-accel Disables accel.
|
--disable-accel Disables accel.
|
||||||
|
|
||||||
Apart from disabling certain features you can very often "strip"
|
Apart from disabling certain features you can very often "strip"
|
||||||
the program of its debugging information resulting in a significant
|
the program of its debugging information resulting in a significant
|
||||||
reduction in size.
|
reduction in size.
|
||||||
@@ -296,7 +299,7 @@ or ~/wxWin or whatever)
|
|||||||
Now the makefiles are created (by configure) and you can compile
|
Now the makefiles are created (by configure) and you can compile
|
||||||
the library by typing:
|
the library by typing:
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|
||||||
make yourself some coffee, as it will take some time. On an old
|
make yourself some coffee, as it will take some time. On an old
|
||||||
386SX possibly two weeks. During compilation, you'll get a few
|
386SX possibly two weeks. During compilation, you'll get a few
|
||||||
@@ -310,16 +313,16 @@ Then you may install the library and its header files under
|
|||||||
have to log in as root (i.e. run "su" and enter the root
|
have to log in as root (i.e. run "su" and enter the root
|
||||||
password) and type
|
password) and type
|
||||||
|
|
||||||
make install
|
make install
|
||||||
|
|
||||||
You can remove any traces of wxWindows by typing
|
You can remove any traces of wxWindows by typing
|
||||||
|
|
||||||
make uninstall
|
make uninstall
|
||||||
|
|
||||||
If you want to save disk space by removing unnecessary
|
If you want to save disk space by removing unnecessary
|
||||||
object-files:
|
object-files:
|
||||||
|
|
||||||
make clean
|
make clean
|
||||||
|
|
||||||
in the various directories will do the work for you.
|
in the various directories will do the work for you.
|
||||||
|
|
||||||
@@ -343,7 +346,7 @@ minimal.o: minimal.cpp mondrian.xpm
|
|||||||
$(CC) `wx-config --cflags` -c minimal.cpp -o minimal.o
|
$(CC) `wx-config --cflags` -c minimal.cpp -o minimal.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o minimal
|
rm -f *.o minimal
|
||||||
|
|
||||||
This is certain to become the standard way unless we decide
|
This is certain to become the standard way unless we decide
|
||||||
to stick to tmake.
|
to stick to tmake.
|
||||||
@@ -370,5 +373,38 @@ go ahead yourself :-)
|
|||||||
In the hope that it will be useful,
|
In the hope that it will be useful,
|
||||||
|
|
||||||
Robert Roebling <roebling@sun2.ruf.uni-freiburg.de>
|
Robert Roebling <roebling@sun2.ruf.uni-freiburg.de>
|
||||||
|
|
||||||
|
|
||||||
|
Addition notes by Julian Smart, August 2002
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
I've fixed some compile errors, and got as far as
|
||||||
|
compiling wxWINE, but actually linking a sample will take
|
||||||
|
further work.
|
||||||
|
|
||||||
|
To compile wxWINE, export these variables:
|
||||||
|
|
||||||
|
export CPPFLAGS=-I/usr/local/include/wine
|
||||||
|
export LDFLAGS=-L/usr/local/lib/wine
|
||||||
|
|
||||||
|
and configure with:
|
||||||
|
|
||||||
|
configure --disable-static --enable-shared --enable-gui \
|
||||||
|
--with-wine --without-libpng --enable-debug_flag --enable-log \
|
||||||
|
--enable-debug_info --enable-ole --enable-clipboard --enable-dataobj \
|
||||||
|
--enable-debug --enable-threads --disable-sockets \
|
||||||
|
--with-libjpeg --enable-debug_cntxt
|
||||||
|
|
||||||
|
Compiling a sample won't work yet because 'winebuild' needs
|
||||||
|
to be called, and the resuling C file compiled and linked.
|
||||||
|
Plus, Windows DLLs need to be imported.
|
||||||
|
|
||||||
|
Note that the documentation on the WINE web site on using
|
||||||
|
winebuild is out of date (August 2002) -- the spec file no
|
||||||
|
longer supports import and type keywords. Instead look at
|
||||||
|
samples in the WINE 'programs' directory for inspiration
|
||||||
|
and compile options to use. It's probable that the
|
||||||
|
wxWINE library will need recompiling with different options.
|
||||||
|
|
||||||
|
Any progress on this front will be very welcome.
|
||||||
|
|
||||||
|
@@ -43,12 +43,17 @@ public:
|
|||||||
|
|
||||||
// get the current tip and update the internal state to return the next tip
|
// get the current tip and update the internal state to return the next tip
|
||||||
// when called for the next time
|
// when called for the next time
|
||||||
virtual wxString GetTip() = 0;
|
virtual wxString GetTip() = 0;
|
||||||
|
|
||||||
// get the current tip "index" (or whatever allows the tip provider to know
|
// get the current tip "index" (or whatever allows the tip provider to know
|
||||||
// from where to start the next time)
|
// from where to start the next time)
|
||||||
size_t GetCurrentTip() const { return m_currentTip; }
|
size_t GetCurrentTip() const { return m_currentTip; }
|
||||||
|
|
||||||
|
// Allows any user-derived class to optionally override this function to
|
||||||
|
// modify the tip as soon as it is read. If return wxEmptyString, then
|
||||||
|
// the tip is skipped, and the next one is read.
|
||||||
|
virtual wxString PreprocessTip(const wxString& tip) { return tip; }
|
||||||
|
|
||||||
// virtual dtor for the base class
|
// virtual dtor for the base class
|
||||||
virtual ~wxTipProvider() { }
|
virtual ~wxTipProvider() { }
|
||||||
|
|
||||||
|
@@ -1,5 +1,18 @@
|
|||||||
Startup tips are documented in "Startup tips overview" section of wxWindows documentation.
|
Startup tips are documented in the "Startup tips overview" section of wxWindows documentation.
|
||||||
This is the first tip!
|
These tips are being read from the tips.txt text file in this directory. Each line of the file contains a single tip.
|
||||||
And this is another great tip...
|
If you close and open this tips dialog, you will notice that the tip numbers start at the point you were at when you closed the dialog last time. This allows easy cycling through the entire list of tips, instead of always showing the initial tips over and over.
|
||||||
And here is a very very very very very very very very very very very long one.
|
Often you will want to save to the application's wxConfig, the last tip that the user saw, as well as whether they want to see tips on startup.
|
||||||
If you have something useful to add to this file, please do.
|
Comments in the tips file have a # as the first character. Comments are automatically skipped over. See the tips.txt file in this directory for the example.
|
||||||
|
# This line is a comment since it started with a #, and is skipped.
|
||||||
|
Blank lines in the tip file are also automatically skipped over. Lines with only spaces are also considered empty.
|
||||||
|
The next line in this tip file is empty, so it will be automatically skipped.
|
||||||
|
|
||||||
|
The next line in this tip file is just empty spaces, so it is considered empty too, and is also automatically skipped.
|
||||||
|
|
||||||
|
You can easily add translations to your startup tips via the usual gettext methods by wrapping a string in a gettext macro, which is _(""). See next tip for example.
|
||||||
|
_("This tip is marked as a translatable string by wrapping it inside the usual gettext macro, so it can be collected by gettext and added to a translation catalog. Your application can then use this catalog and serve out a translated version of the tip.")
|
||||||
|
Translatable strings must strictly begin with _(", not _( " or wxGetTranslation(" or something else.
|
||||||
|
If you are using gettext translatable strings, don't forget to escape to replace any " characters within the tip with a \" instead
|
||||||
|
_("This is a translatable tip with the quoted words \"Escape me\" properly escaped.")
|
||||||
|
If you have very specialized needs, you can derive your own wxTipProvider and use that instead.
|
||||||
|
If you want to modify the tip content at runtime for purposes other than translation (for example, variable expansion), one easy option is to use a custom tip provider derived from wxFileTipProvider. Your custom tip provider would contain a single virtual function to override: PreprocessTip().
|
||||||
|
@@ -136,17 +136,56 @@ wxString wxFileTipProvider::GetTip()
|
|||||||
{
|
{
|
||||||
size_t count = m_textfile.GetLineCount();
|
size_t count = m_textfile.GetLineCount();
|
||||||
if ( !count )
|
if ( !count )
|
||||||
return _("Tips not available, sorry!");
|
|
||||||
|
|
||||||
// notice that it may be greater, actually, if we remembered it from the
|
|
||||||
// last time and the number of tips changed
|
|
||||||
if ( m_currentTip == count )
|
|
||||||
{
|
{
|
||||||
// wrap
|
return _("Tips not available, sorry!");
|
||||||
m_currentTip = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString tip;
|
||||||
|
|
||||||
return m_textfile.GetLine(m_currentTip++);
|
// Comments start with a # symbol.
|
||||||
|
// Loop reading lines until get the first one that isn't a comment.
|
||||||
|
// The max number of loop executions is the number of lines in the
|
||||||
|
// textfile so that can't go into an eternal loop in the [oddball]
|
||||||
|
// case of a comment-only tips file, or the developer has vetoed
|
||||||
|
// them all via PreprecessTip().
|
||||||
|
for ( size_t i=0; i < count; i++ )
|
||||||
|
{
|
||||||
|
// The current tip may be at the last line of the textfile, (or
|
||||||
|
// past it, if the number of lines in the textfile changed, such
|
||||||
|
// as changing to a different textfile, with less tips). So check
|
||||||
|
// to see at last line of text file, (or past it)...
|
||||||
|
if ( m_currentTip >= count )
|
||||||
|
{
|
||||||
|
// .. and if so, wrap back to line 0.
|
||||||
|
m_currentTip = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the tip, and increment the current tip counter.
|
||||||
|
tip = m_textfile.GetLine(m_currentTip++);
|
||||||
|
|
||||||
|
// Allow a derived class's overrided virtual to modify the tip
|
||||||
|
// now if so desired.
|
||||||
|
tip = PreprocessTip(tip);
|
||||||
|
|
||||||
|
// Break if tip isn't a comment, and isn't an empty string
|
||||||
|
// (or only stray space characters).
|
||||||
|
if ( !tip.StartsWith(wxT("#")) && (tip.Trim() != wxEmptyString) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tip starts with '_(', then it is a gettext string of format
|
||||||
|
// _("My \"global\" tip text") so first strip off the leading '_("'...
|
||||||
|
if ( tip.StartsWith(wxT("_(\"" ), &tip))
|
||||||
|
{
|
||||||
|
//...and strip off the trailing '")'...
|
||||||
|
tip = tip.BeforeLast(wxT('\"'));
|
||||||
|
// ...and replace escaped quotes
|
||||||
|
tip.Replace(wxT("\\\""), wxT("\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tip;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user