first commit

This commit is contained in:
Mengjuei Hsieh 2011-09-01 23:56:26 -07:00
commit 5f976e4642
144 changed files with 48545 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
build
*.pbxuser
*.mode1v3
*.tm_build_errors
*.dmg
.DS_Store
project.xcworkspace
xcuserdata

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>CocoaDialog</string>
<key>CFBundleIconFile</key>
<string>cocoadialog</string>
<key>CFBundleIdentifier</key>
<string>org.sporkstorms.CocoaDialog</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.1.1</string>
<key>LSUIElement</key>
<integer>1</integer>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1 @@
APPL????

View File

@ -0,0 +1,281 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,73 @@
2.1.0 April 26, 2006
- Implemented --packages-as-directories in fileselect.
2.1.0 Feb 26, 2006
- Compiled as a Universal Binary
- Intelligent resizing to accommodate --informative-text in
all inputbox dialogs, all msgbox dialogs, and textbox.
Same for --text in all dropdown dialogs.
- New "filesave" dialogs
- Added --packages-as-directories option to fileselect.
- Added --x-placement and --y-placement to bubble.
2.0.0 Jan 2, 2006
- Added bubble dialog.
- Added secure modes for inputbox and standard-inputbox.
- The application now runs as a background app. This means no more annoying
menu or dock icon!
- Some dialogs can be floated above all other applications.
- Timeouts on several dialogs.
- Intelligent button resizing
- Added custom icon support to msgbox, ok-msgbox, and standard-msgbox.
- Added --help options (still needs improvement).
- Added --select-only-directories to fileselect.
- Restructured project directory, code hierarchy, and refactored much of the code.
- Cleaned up the look of several dialogs.
- Progressbar won't be displayed right away, to prevent showing for
very short operations.
- Bug fixes (string-input on inputboxes, missing deallocs).
- New application icon.
1.2.2
- (Didn't release)
- Allan's patch
1.2.1 Jan, 2005
- (Did I even release this?).
- Wout's patch:
added --no-show, --float, --timeout and --help options
turned into a background app so that the dialog icon does not show
up in the menu bar. This, together with float, is very useful for
loginhooks.
1.2.0 Dec 28, 2004
- added dropdown and standard-dropdown controls.
1.1.3 May 11, 2004
- fixed handling of multi-line input to progressbar.
1.1.2 May 10, 2004
- fixed crash that would occur when printing return values containing
non-Roman characters. Thanks to Nobumi Iyanaga for finding this.
- added "debug" class method to CDControl and got rid of those
printf()s.
1.1.1 April 26, 2004
- starting to use x.y.z versioning (instead of x.y)
- progressbar incorrectly printed error with --debug
(runControlFromOptions: always returned nil, which should only happen
on error). This has been fixed.
- progressbar character encoding bug fixed. should now properly handle
UTF8 labels read from stdin. see bug 942012 on sf.net page. thanks to
J-F Boquillard for finding and fixing this.
1.1
- added inputbox, standard-inputbox
- textbox window no longer closes on escape unless there's a "Cancel"
button
- fixed error handling for textbox when --text-from-file file is
invalid.
1.0
- initial release

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>CocoaDialog</string>
<key>CFBundleIconFile</key>
<string>cocoadialog</string>
<key>CFBundleIdentifier</key>
<string>org.sporkstorms.CocoaDialog</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.1.1</string>
<key>LSUIElement</key>
<integer>1</integer>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,51 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = CDInputboxControl;
LANGUAGE = ObjC;
OUTLETS = {textField = NSTextField; };
SUPERCLASS = CDThreeButtonControl;
},
{
CLASS = CDMsgboxControl;
LANGUAGE = ObjC;
OUTLETS = {imageView = NSImageView; text = NSTextField; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {selectionChanged = id; };
CLASS = CDPopUpButtonControl;
LANGUAGE = ObjC;
OUTLETS = {popup = NSPopUpButton; };
SUPERCLASS = CDThreeButtonControl;
},
{
CLASS = CDProgressbarControl;
LANGUAGE = ObjC;
OUTLETS = {label = NSTextField; panel = NSPanel; progressBar = NSProgressIndicator; };
SUPERCLASS = CDControl;
},
{
CLASS = CDTextboxControl;
LANGUAGE = ObjC;
OUTLETS = {textView = NSTextView; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
CLASS = CDThreeButtonControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
expandingLabel = NSTextField;
panel = NSPanel;
};
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>76 119 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8H14</string>
</dict>
</plist>

View File

@ -0,0 +1,7 @@
{
IBClasses = (
{CLASS = AppController; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>373 505 356 240 0 0 1680 1028 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>131 353 216 44 0 0 1680 1028 </string>
</dict>
<key>IBFramework Version</key>
<string>364.0</string>
<key>IBOpenObjects</key>
<array>
<integer>29</integer>
</array>
<key>IBSystem Version</key>
<string>7R28</string>
</dict>
</plist>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>188 324 356 240 0 0 1024 746 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>69 252 299 44 0 0 1024 746 </string>
</dict>
<key>IBFramework Version</key>
<string>349.0</string>
<key>IBOpenObjects</key>
<array>
<integer>29</integer>
</array>
<key>IBSystem Version</key>
<string>7F44</string>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1,27 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = CDMsgboxControl;
LANGUAGE = ObjC;
OUTLETS = {imageView = NSImageView; text = NSTextField; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
CLASS = CDThreeButtonControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
expandingLabel = NSTextField;
panel = NSPanel;
};
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{CLASS = "java.lang.Object"; LANGUAGE = Java; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>57 203 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>10</integer>
</array>
<key>IBSystem Version</key>
<string>8H14</string>
</dict>
</plist>

View File

@ -0,0 +1,55 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
CLASS = CDInputboxControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
label = NSTextField;
panel = NSPanel;
textField = NSTextField;
};
SUPERCLASS = CDControl;
},
{
ACTIONS = {selectionChanged = id; };
CLASS = CDPopUpButtonControl;
LANGUAGE = ObjC;
OUTLETS = {popup = NSPopUpButton; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
CLASS = CDTextboxControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
label = NSTextField;
panel = NSPanel;
textView = NSTextView;
};
SUPERCLASS = CDControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
CLASS = CDThreeButtonControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
expandingLabel = NSTextField;
panel = NSPanel;
};
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>120 158 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8H14</string>
</dict>
</plist>

View File

@ -0,0 +1,13 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = CDProgressbarControl;
LANGUAGE = ObjC;
OUTLETS = {label = NSTextField; panel = NSPanel; progressBar = NSProgressIndicator; };
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>128 15 356 240 0 0 1600 1002 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8F46</string>
</dict>
</plist>

View File

@ -0,0 +1,40 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = CDInputboxControl;
LANGUAGE = ObjC;
OUTLETS = {textField = NSTextField; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; };
CLASS = CDTextboxControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
label = NSTextField;
panel = NSPanel;
textView = NSTextView;
};
SUPERCLASS = CDControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
CLASS = CDThreeButtonControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
expandingLabel = NSTextField;
panel = NSPanel;
};
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>82 210 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8H14</string>
</dict>
</plist>

View File

@ -0,0 +1,26 @@
{
IBClasses = (
{CLASS = CDControl; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = CDTextboxControl;
LANGUAGE = ObjC;
OUTLETS = {textView = NSTextView; };
SUPERCLASS = CDThreeButtonControl;
},
{
ACTIONS = {button1Pressed = id; button2Pressed = id; button3Pressed = id; timeout = id; };
CLASS = CDThreeButtonControl;
LANGUAGE = ObjC;
OUTLETS = {
button1 = NSButton;
button2 = NSButton;
button3 = NSButton;
expandingLabel = NSTextField;
panel = NSPanel;
};
SUPERCLASS = CDControl;
},
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>117 70 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8H14</string>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

39
Installer/Script.bash Normal file
View File

@ -0,0 +1,39 @@
#!/bin/bash
# The following files are bundled:
#
# 'Lettuce.app'
# 'CocoaDialog.app'
# 'pic_normal.png'
#
myLicense="Copyright (c) 2011, the Openvanilla Project
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
CD="CocoaDialog.app/Contents/MacOS/CocoaDialog"
rv=$($CD yesno-msgbox --title "License Agreement" --text "Agree this before you install. :-)" --informative-text "$myLicense" --string-output --no-cancel)
if [ $rv == "No" ]; then
exit 0
fi
if [ $(/bin/ps xww|/usr/bin/awk '/Lettuce/{bm=1}END{print bm}')"blah" != "blah1" ]; then
killall -9 Lettuce
echo PROGRESS:25
fi
if [ ! -e $HOME/Library/Input\ Methods ]; then
mkdir -p $HOME/Library/Input\ Methods
echo PROGRESS:50
else
echo PROGRESS:50
fi
cp -R Lettuce.app $HOME/Library/Input\ Methods/
echo PROGRESS:75
$HOME/Library/Input\ Methods/Lettuce.app/Contents/MacOS/Lettuce install
echo PROGRESS:100
$CD bubble --debug --title "Thank you!" --text "McBoPoMoPo has been installed." --icon-file pic_normal.png

BIN
Installer/pic_normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

1
README.markdown Normal file
View File

@ -0,0 +1 @@
Lettuce Project

50
Source/AppDelegate.h Normal file
View File

@ -0,0 +1,50 @@
//
// AppDelegate.h
//
// Copyright (c) 2011 The McBopomofo Project.
//
// Contributors:
// Mengjuei Hsieh (@mjhsieh)
// Weizhong Yang (@zonble)
//
// Based on the Syrup Project and the Formosana Library
// by Lukhnos Liu (@lukhnos).
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#import <Cocoa/Cocoa.h>
@class UpdateNotificationController;
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
@private
NSWindow *_window;
NSURLConnection *_updateCheckConnection;
UpdateNotificationController *_updateNotificationController;
}
- (void)checkForUpdate;
@property (assign) IBOutlet NSWindow *window;
@end

171
Source/AppDelegate.m Normal file
View File

@ -0,0 +1,171 @@
//
// AppDelegate.m
//
// Copyright (c) 2011 The McBopomofo Project.
//
// Contributors:
// Mengjuei Hsieh (@mjhsieh)
// Weizhong Yang (@zonble)
//
// Based on the Syrup Project and the Formosana Library
// by Lukhnos Liu (@lukhnos).
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#import "AppDelegate.h"
#import "UpdateNotificationController.h"
void LTLoadLanugageModel();
static NSString *kNextUpdateCheckDateKey = @"NextUpdateCheckDate";
static NSString *kUpdateInfoEndpointKey = @"UpdateInfoEndpoint";
static NSString *kUpdateInfoSiteKey = @"UpdateInfoSite";
static const NSTimeInterval kTimeoutInterval = 10.0;
static const NSTimeInterval kNextCheckInterval = 86400.0;
@implementation AppDelegate
@synthesize window = _window;
- (void)dealloc
{
[_updateCheckConnection release];
[_updateNotificationController release];
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification *)inNotification
{
LTLoadLanugageModel();
[self checkForUpdate];
}
- (void)checkForUpdate
{
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:kNextUpdateCheckDateKey];
if (![date isKindOfClass:[NSDate class]]) {
date = [NSDate date];
}
if ([(NSDate *)[NSDate date] compare:date] == NSOrderedAscending) {
return;
}
NSDate *nextUpdateDate = [NSDate dateWithTimeInterval:kNextCheckInterval sinceDate:[NSDate date]];
[[NSUserDefaults standardUserDefaults] setObject:nextUpdateDate forKey:kNextUpdateCheckDateKey];
if (_updateCheckConnection) {
[_updateCheckConnection release];
_updateCheckConnection = nil;
}
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *updateInfoURLString = [infoDict objectForKey:kUpdateInfoEndpointKey];
if (![updateInfoURLString length]) {
return;
}
NSURL *updateInfoURL = [NSURL URLWithString:updateInfoURLString];
if (!updateInfoURL) {
return;
}
NSURLRequest *request = [NSURLRequest requestWithURL:updateInfoURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:kTimeoutInterval];
if (!request) {
return;
}
#if DEBUG
NSLog(@"about to request update url %@ ",updateInfoURL);
#endif
_updateCheckConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[_updateCheckConnection start];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"error");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
id plist = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL];
#if DEBUG
NSLog(@"plist %@",plist);
#endif
if (!plist) {
return;
}
NSString *remoteVersion = [plist objectForKey:(id)kCFBundleVersionKey];
#if DEBUG
NSLog(@"the remoteversion is %@",remoteVersion);
#endif
if (!remoteVersion) {
return;
}
// TODO: Validate info (e.g. bundle identifier)
// TODO: Use HTML to display change log, need a new key like UpdateInfoChangeLogURL for this
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *currentVersion = [infoDict objectForKey:(id)kCFBundleVersionKey];
NSComparisonResult result = [currentVersion compare:remoteVersion options:NSNumericSearch];
if (result != NSOrderedAscending) {
return;
}
NSString *siteInfoURLString = [plist objectForKey:kUpdateInfoSiteKey];
if (!siteInfoURLString) {
return;
}
NSURL *siteInfoURL = [NSURL URLWithString:siteInfoURLString];
if (!siteInfoURL) {
return;
}
if (_updateNotificationController) {
[_updateNotificationController release], _updateNotificationController = nil;
}
_updateNotificationController = [[UpdateNotificationController alloc] initWithWindowNibName:@"UpdateNotificationController"];
_updateNotificationController.siteURL = siteInfoURL;
_updateNotificationController.infoText = [NSString stringWithFormat:NSLocalizedString(@"You are running version %@ (%@), and the new version %@ (%@) is now available.\n\nVisit the website to download it?", @""),
[infoDict objectForKey:@"CFBundleShortVersionString"],
[infoDict objectForKey:(id)kCFBundleVersionKey],
[plist objectForKey:@"CFBundleShortVersionString"],
[plist objectForKey:(id)kCFBundleVersionKey],
nil];
[_updateNotificationController showWindow:self];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
@end

View File

@ -0,0 +1,104 @@
//
// Bigram.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Bigram_h
#define Bigram_h
#include "KeyValuePair.h"
namespace Formosa {
namespace Gramambular {
class Bigram {
public:
Bigram();
KeyValuePair preceedingKeyValue;
KeyValuePair keyValue;
double score;
bool operator==(const Bigram& inAnother) const;
bool operator<(const Bigram& inAnother) const;
};
inline ostream& operator<<(ostream& inStream, const Bigram& inGram)
{
streamsize p = inStream.precision();
inStream.precision(6);
inStream << "(" << inGram.keyValue << "|" <<inGram.preceedingKeyValue << "," << inGram.score << ")";
inStream.precision(p);
return inStream;
}
inline ostream& operator<<(ostream& inStream, const vector<Bigram>& inGrams)
{
inStream << "[" << inGrams.size() << "]=>{";
size_t index = 0;
for (vector<Bigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
inStream << index << "=>";
inStream << *gi;
if (gi + 1 != inGrams.end()) {
inStream << ",";
}
}
inStream << "}";
return inStream;
}
inline Bigram::Bigram()
: score(0.0)
{
}
inline bool Bigram::operator==(const Bigram& inAnother) const
{
return preceedingKeyValue == inAnother.preceedingKeyValue && keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Bigram::operator<(const Bigram& inAnother) const
{
if (preceedingKeyValue < inAnother.preceedingKeyValue) {
return true;
}
else if (preceedingKeyValue == inAnother.preceedingKeyValue) {
if (keyValue < inAnother.keyValue) {
return true;
}
else if (keyValue == inAnother.keyValue) {
return score < inAnother.score;
}
return false;
}
return false;
}
}
}
#endif

View File

@ -0,0 +1,216 @@
//
// BlockReadingBuilder.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef BlockReadingBuilder_h
#define BlockReadingBuilder_h
#include <vector>
#include "Grid.h"
#include "LanguageModel.h"
namespace Formosa {
namespace Gramambular {
using namespace std;
class BlockReadingBuilder {
public:
BlockReadingBuilder(LanguageModel *inLM);
void clear();
size_t length() const;
size_t cursorIndex() const;
void setCursorIndex(size_t inNewIndex);
void insertReadingAtCursor(const string& inReading);
bool deleteReadingBeforeCursor(); // backspace
bool deleteReadingAfterCursor(); // delete
bool removeHeadReadings(size_t count);
void setJoinSeparator(const string& separator);
const string joinSeparator() const;
Grid& grid();
protected:
void build();
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator);
static const size_t MaximumBuildSpanLength = 4;
size_t m_cursorIndex;
vector<string> m_readings;
Grid m_grid;
LanguageModel *m_LM;
string m_joinSeparator;
};
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
: m_LM(inLM)
, m_cursorIndex(0)
{
}
inline void BlockReadingBuilder::clear()
{
m_cursorIndex = 0;
m_readings.clear();
m_grid.clear();
}
inline size_t BlockReadingBuilder::length() const
{
return m_readings.size();
}
inline size_t BlockReadingBuilder::cursorIndex() const
{
return m_cursorIndex;
}
inline void BlockReadingBuilder::setCursorIndex(size_t inNewIndex)
{
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
}
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
{
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
m_grid.expandGridByOneAtLocation(m_cursorIndex);
build();
m_cursorIndex++;
}
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
{
if (!m_cursorIndex) {
return false;
}
m_readings.erase(m_readings.begin() + m_cursorIndex - 1, m_readings.begin() + m_cursorIndex);
m_cursorIndex--;
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
inline bool BlockReadingBuilder::deleteReadingAfterCursor()
{
if (m_cursorIndex == m_readings.size()) {
return false;
}
m_readings.erase(m_readings.begin() + m_cursorIndex, m_readings.begin() + m_cursorIndex + 1);
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
inline bool BlockReadingBuilder::removeHeadReadings(size_t count)
{
if (count > length()) {
return false;
}
for (size_t i = 0; i < count; i++) {
if (m_cursorIndex) {
m_cursorIndex--;
}
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
m_grid.shrinkGridByOneAtLocation(0);
build();
}
return true;
}
inline void BlockReadingBuilder::setJoinSeparator(const string& separator)
{
m_joinSeparator = separator;
}
inline const string BlockReadingBuilder::joinSeparator() const
{
return m_joinSeparator;
}
inline Grid& BlockReadingBuilder::grid()
{
return m_grid;
}
inline void BlockReadingBuilder::build()
{
if (!m_LM) {
return;
}
size_t begin = 0;
size_t end = m_cursorIndex + MaximumBuildSpanLength;
if (m_cursorIndex < MaximumBuildSpanLength) {
begin = 0;
}
else {
begin = m_cursorIndex - MaximumBuildSpanLength;
}
if (end > m_readings.size()) {
end = m_readings.size();
}
for (size_t p = begin ; p < end ; p++) {
for (size_t q = 1 ; q <= MaximumBuildSpanLength && p+q <= end ; q++) {
string combinedReading = Join(m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
if (m_LM->hasUnigramsForKey(combinedReading) && !m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q, combinedReading)) {
Node n(combinedReading, m_LM->unigramsForKeys(combinedReading), vector<Bigram>());
m_grid.insertNode(n, p, q);
}
}
}
}
const string BlockReadingBuilder::Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
{
string result;
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
result += *iter;
++iter;
if (iter != end) {
result += separator;
}
}
return result;
}
}
}
#endif

View File

@ -0,0 +1,42 @@
//
// Gramambular.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Gramambular_h
#define Gramambular_h
#include "Bigram.h"
#include "BlockReadingBuilder.h"
#include "Grid.h"
#include "KeyValuePair.h"
#include "LanguageModel.h"
#include "Node.h"
#include "NodeAnchor.h"
#include "Span.h"
#include "Unigram.h"
#include "Walker.h"
#endif

View File

@ -0,0 +1,221 @@
//
// Grid.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Grid_h
#define Grid_h
#include <map>
#include "NodeAnchor.h"
#include "Span.h"
namespace Formosa {
namespace Gramambular {
class Grid {
public:
void clear();
void insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength);
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey);
void expandGridByOneAtLocation(size_t inLocation);
void shrinkGridByOneAtLocation(size_t inLocation);
size_t width() const;
vector<NodeAnchor> nodesEndingAt(size_t inLocation);
vector<NodeAnchor> nodesCrossingOrEndingAt(size_t inLocation);
const string dumpDOT();
protected:
vector<Span> m_spans;
};
inline void Grid::clear()
{
m_spans.clear();
}
inline void Grid::insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength)
{
if (inLocation >= m_spans.size()) {
size_t diff = inLocation - m_spans.size() + 1;
for (size_t i = 0 ; i < diff ; i++) {
m_spans.push_back(Span());
}
}
m_spans[inLocation].insertNodeOfLength(inNode, inSpanningLength);
}
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey)
{
if (inLocation > m_spans.size()) {
return false;
}
const Node *n = m_spans[inLocation].nodeOfLength(inSpanningLength);
if (!n) {
return false;
}
return inKey == n->key();
}
inline void Grid::expandGridByOneAtLocation(size_t inLocation)
{
if (!inLocation || inLocation == m_spans.size()) {
m_spans.insert(m_spans.begin() + inLocation, Span());
}
else {
m_spans.insert(m_spans.begin() + inLocation, Span());
for (size_t i = 0 ; i < inLocation ; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
}
}
}
inline void Grid::shrinkGridByOneAtLocation(size_t inLocation)
{
if (inLocation >= m_spans.size()) {
return;
}
m_spans.erase(m_spans.begin() + inLocation);
for (size_t i = 0 ; i < inLocation ; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
}
}
inline size_t Grid::width() const
{
return m_spans.size();
}
inline vector<NodeAnchor> Grid::nodesEndingAt(size_t inLocation)
{
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) {
Node *np = span.nodeOfLength(inLocation - i);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = inLocation - i;
result.push_back(na);
}
}
}
}
return result;
}
inline vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t inLocation)
{
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) {
for (size_t j = 1, m = span.maximumLength(); j <= m ; j++) {
if (i + j < inLocation) {
continue;
}
Node *np = span.nodeOfLength(j);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = inLocation - i;
result.push_back(na);
}
}
}
}
}
return result;
}
inline const string Grid::dumpDOT()
{
stringstream sst;
sst << "digraph {" << endl;
sst << "graph [ rankdir=LR ];" << endl;
sst << "BOS;" << endl;
for (size_t p = 0 ; p < m_spans.size() ; p++) {
Span& span = m_spans[p];
for (size_t ni = 0 ; ni <= span.maximumLength() ; ni++) {
Node* np = span.nodeOfLength(ni);
if (np) {
if (!p) {
sst << "BOS -> " << np->currentKeyValue().value << ";" << endl;
}
sst << np->currentKeyValue().value << ";" << endl;
if (p + ni < m_spans.size()) {
Span& dstSpan = m_spans[p+ni];
for (size_t q = 0 ; q <= dstSpan.maximumLength() ; q++) {
Node *dn = dstSpan.nodeOfLength(q);
if (dn) {
sst << np->currentKeyValue().value << " -> " << dn->currentKeyValue().value << ";" << endl;
}
}
}
if (p + ni == m_spans.size()) {
sst << np->currentKeyValue().value << " -> " << "EOS;" << endl;
}
}
}
}
sst << "EOS;" << endl;
sst << "}";
return sst.str();
}
}
}
#endif

View File

@ -0,0 +1,70 @@
//
// KeyValuePair.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef KeyValuePair_h
#define KeyValuePair_h
#include <string>
namespace Formosa {
namespace Gramambular {
using namespace std;
class KeyValuePair {
public:
string key;
string value;
bool operator==(const KeyValuePair& inAnother) const;
bool operator<(const KeyValuePair& inAnother) const;
};
inline ostream& operator<<(ostream& inStream, const KeyValuePair& inPair)
{
inStream << "(" << inPair.key << "," << inPair.value << ")";
return inStream;
}
inline bool KeyValuePair::operator==(const KeyValuePair& inAnother) const
{
return key == inAnother.key && value == inAnother.value;
}
inline bool KeyValuePair::operator<(const KeyValuePair& inAnother) const
{
if (key < inAnother.key) {
return true;
}
else if (key == inAnother.key) {
return value < inAnother.value;
}
return false;
}
}
}
#endif

View File

@ -0,0 +1,52 @@
//
// LanguageModel.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef LanguageModel_h
#define LanguageModel_h
#include <vector>
#include "Bigram.h"
#include "Unigram.h"
namespace Formosa {
namespace Gramambular {
using namespace std;
class LanguageModel {
public:
virtual ~LanguageModel() {}
virtual const vector<Bigram> bigramsForKeys(const string &preceedingKey, const string& key) = 0;
virtual const vector<Unigram> unigramsForKeys(const string &key) = 0;
virtual bool hasUnigramsForKey(const string& key) = 0;
};
}
}
#endif

View File

@ -0,0 +1,191 @@
//
// Node.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Node_h
#define Node_h
#include <limits>
#include <vector>
#include "LanguageModel.h"
namespace Formosa {
namespace Gramambular {
using namespace std;
class Node {
public:
Node();
Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams);
void primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues);
bool isCandidateFixed() const;
const vector<KeyValuePair>& candidates() const;
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true);
const string& key() const;
double score() const;
const KeyValuePair currentKeyValue() const;
protected:
const LanguageModel* m_LM;
string m_key;
double m_score;
vector<Unigram> m_unigrams;
vector<KeyValuePair> m_candidates;
map<string, size_t> m_valueUnigramIndexMap;
map<KeyValuePair, vector<Bigram> > m_preceedingGramBigramMap;
bool m_candidateFixed;
size_t m_selectedUnigramIndex;
friend ostream& operator<<(ostream& inStream, const Node& inNode);
};
inline ostream& operator<<(ostream& inStream, const Node& inNode)
{
inStream << "(node,key:" << inNode.m_key << ",fixed:" << (inNode.m_candidateFixed ? "true" : "false")
<< ",selected:" << inNode.m_selectedUnigramIndex
<< "," << inNode.m_unigrams << ")";
return inStream;
}
inline Node::Node()
: m_candidateFixed(false)
, m_selectedUnigramIndex(0)
, m_score(0.0)
{
}
inline Node::Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams)
: m_key(inKey)
, m_unigrams(inUnigrams)
, m_candidateFixed(false)
, m_selectedUnigramIndex(0)
, m_score(0.0)
{
sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
if (m_unigrams.size()) {
m_score = m_unigrams[0].score;
}
size_t i = 0;
for (vector<Unigram>::const_iterator ui = m_unigrams.begin() ; ui != m_unigrams.end() ; ++ui) {
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
i++;
m_candidates.push_back((*ui).keyValue);
}
for (vector<Bigram>::const_iterator bi = inBigrams.begin() ; bi != inBigrams.end() ; ++bi) {
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
}
}
inline void Node::primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues)
{
size_t newIndex = m_selectedUnigramIndex;
double max = m_score;
if (!isCandidateFixed()) {
for (vector<KeyValuePair>::const_iterator kvi = inKeyValues.begin() ; kvi != inKeyValues.end() ; ++kvi) {
map<KeyValuePair, vector<Bigram> >::const_iterator f = m_preceedingGramBigramMap.find(*kvi);
if (f != m_preceedingGramBigramMap.end()) {
const vector<Bigram>& bigrams = (*f).second;
for (vector<Bigram>::const_iterator bi = bigrams.begin() ; bi != bigrams.end() ; ++bi) {
const Bigram& bigram = *bi;
if (bigram.score > max) {
map<string, size_t>::const_iterator uf = m_valueUnigramIndexMap.find((*bi).keyValue.value);
if (uf != m_valueUnigramIndexMap.end()) {
newIndex = (*uf).second;
max = bigram.score;
}
}
}
}
}
}
if (m_score != max) {
m_score = max;
}
if (newIndex != m_selectedUnigramIndex) {
m_selectedUnigramIndex = newIndex;
}
}
inline bool Node::isCandidateFixed() const
{
return m_candidateFixed;
}
inline const vector<KeyValuePair>& Node::candidates() const
{
return m_candidates;
}
inline void Node::selectCandidateAtIndex(size_t inIndex, bool inFix)
{
if (inIndex >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
}
else {
m_selectedUnigramIndex = inIndex;
}
m_candidateFixed = inFix;
m_score = 99;
}
inline const string& Node::key() const
{
return m_key;
}
inline double Node::score() const
{
return m_score;
}
inline const KeyValuePair Node::currentKeyValue() const
{
if(m_selectedUnigramIndex >= m_unigrams.size()) {
return KeyValuePair();
}
else {
return m_candidates[m_selectedUnigramIndex];
}
}
}
}
#endif

View File

@ -0,0 +1,79 @@
//
// NodeAnchor.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef NodeAnchor_h
#define NodeAnchor_h
#include "Node.h"
namespace Formosa {
namespace Gramambular {
class NodeAnchor {
public:
NodeAnchor();
const Node *node;
size_t location;
size_t spanningLength;
double accumulatedScore;
};
inline NodeAnchor::NodeAnchor()
: node(0)
, location(0)
, spanningLength(0)
, accumulatedScore(0.0)
{
}
inline ostream& operator<<(ostream& inStream, const NodeAnchor& inAnchor)
{
inStream << "{@(" << inAnchor.location << "," << inAnchor.spanningLength << "),";
if (inAnchor.node) {
inStream << *(inAnchor.node);
}
else {
inStream << "null";
}
inStream << "}";
return inStream;
}
inline ostream& operator<<(ostream& inStream, const vector<NodeAnchor>& inAnchor)
{
for (vector<NodeAnchor>::const_iterator i = inAnchor.begin() ; i != inAnchor.end() ; ++i) {
inStream << *i;
if (i + 1 != inAnchor.end()) {
inStream << "<-";
}
}
return inStream;
}
}
}
#endif

View File

@ -0,0 +1,106 @@
//
// Span.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Span_h
#define Span_h
#include <map>
#include <sstream>
#include "Node.h"
namespace Formosa {
namespace Gramambular {
class Span {
public:
Span();
void clear();
void insertNodeOfLength(const Node& inNode, size_t inLength);
void removeNodeOfLengthGreaterThan(size_t inLength);
Node* nodeOfLength(size_t inLength);
size_t maximumLength() const;
protected:
map<size_t, Node> m_lengthNodeMap;
size_t m_maximumLength;
};
inline Span::Span()
: m_maximumLength(0)
{
}
inline void Span::clear()
{
m_lengthNodeMap.clear();
m_maximumLength = 0;
}
inline void Span::insertNodeOfLength(const Node& inNode, size_t inLength)
{
m_lengthNodeMap[inLength] = inNode;
if (inLength > m_maximumLength) {
m_maximumLength = inLength;
}
}
inline void Span::removeNodeOfLengthGreaterThan(size_t inLength)
{
if (inLength > m_maximumLength) {
return;
}
size_t max = 0;
for (map<size_t, Node>::iterator i = m_lengthNodeMap.begin() ; i != m_lengthNodeMap.end() ; ++i) {
if ((*i).first > inLength) {
m_lengthNodeMap.erase(i);
}
else {
if ((*i).first > max) {
max = (*i).first;
}
}
}
m_maximumLength = max;
}
inline Node* Span::nodeOfLength(size_t inLength)
{
map<size_t, Node>::iterator f = m_lengthNodeMap.find(inLength);
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
}
inline size_t Span::maximumLength() const
{
return m_maximumLength;
}
}
}
#endif

View File

@ -0,0 +1,104 @@
//
// Unigram.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Unigram_h
#define Unigram_h
#include <vector>
#include "KeyValuePair.h"
namespace Formosa {
namespace Gramambular {
class Unigram {
public:
Unigram();
KeyValuePair keyValue;
double score;
bool operator==(const Unigram& inAnother) const;
bool operator<(const Unigram& inAnother) const;
static bool ScoreCompare(const Unigram& a, const Unigram& b);
};
inline ostream& operator<<(ostream& inStream, const Unigram& inGram)
{
streamsize p = inStream.precision();
inStream.precision(6);
inStream << "(" << inGram.keyValue << "," << inGram.score << ")";
inStream.precision(p);
return inStream;
}
inline ostream& operator<<(ostream& inStream, const vector<Unigram>& inGrams)
{
inStream << "[" << inGrams.size() << "]=>{";
size_t index = 0;
for (vector<Unigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
inStream << index << "=>";
inStream << *gi;
if (gi + 1 != inGrams.end()) {
inStream << ",";
}
}
inStream << "}";
return inStream;
}
inline Unigram::Unigram()
: score(0.0)
{
}
inline bool Unigram::operator==(const Unigram& inAnother) const
{
return keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Unigram::operator<(const Unigram& inAnother) const
{
if (keyValue < inAnother.keyValue) {
return true;
}
else if (keyValue == inAnother.keyValue) {
return score < inAnother.score;
}
return false;
}
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b)
{
return a.score > b.score;
}
}
}
#endif

View File

@ -0,0 +1,91 @@
//
// Walker.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Walker_h
#define Walker_h
#include <algorithm>
#include "Grid.h"
namespace Formosa {
namespace Gramambular {
using namespace std;
class Walker {
public:
Walker(Grid* inGrid);
const vector<NodeAnchor> reverseWalk(size_t inLocation, double inAccumulatedScore = 0.0);
protected:
Grid* m_grid;
};
inline Walker::Walker(Grid* inGrid)
: m_grid(inGrid)
{
}
inline const vector<NodeAnchor> Walker::reverseWalk(size_t inLocation, double inAccumulatedScore)
{
if (!inLocation || inLocation > m_grid->width()) {
return vector<NodeAnchor>();
}
vector<vector<NodeAnchor> > paths;
vector<NodeAnchor> nodes = m_grid->nodesEndingAt(inLocation);
for (vector<NodeAnchor>::iterator ni = nodes.begin() ; ni != nodes.end() ; ++ni) {
if (!(*ni).node) {
continue;
}
(*ni).accumulatedScore = inAccumulatedScore + (*ni).node->score();
vector<NodeAnchor> path = reverseWalk(inLocation - (*ni).spanningLength, (*ni).accumulatedScore);
path.insert(path.begin(), *ni);
paths.push_back(path);
}
if (!paths.size()) {
return vector<NodeAnchor>();
}
vector<NodeAnchor>* result = &*(paths.begin());
for (vector<vector<NodeAnchor> >::iterator pi = paths.begin() ; pi != paths.end() ; ++pi) {
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
result = &*pi;
}
}
return *result;
}
}
}
#endif

View File

@ -0,0 +1,956 @@
//
// Mandarin.cpp
//
// Copyright (c) 2006-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include <cctype>
#include <algorithm>
#include "Mandarin.h"
#include "OVUTF8Helper.h"
#include "OVWildcard.h"
namespace Formosa {
namespace Mandarin {
using namespace OpenVanilla;
class PinyinParseHelper {
public:
static const bool ConsumePrefix(string &target, const string &prefix)
{
if (target.length() < prefix.length()) {
return false;
}
if (target.substr(0, prefix.length()) == prefix) {
target = target.substr(prefix.length(), target.length() - prefix.length());
return true;
}
return false;
}
};
class BopomofoCharacterMap {
public:
static const BopomofoCharacterMap& SharedInstance();
map<BPMF::Component, string> componentToCharacter;
map<string, BPMF::Component> characterToComponent;
protected:
BopomofoCharacterMap();
static BopomofoCharacterMap* c_map;
};
const BPMF BPMF::FromHanyuPinyin(const string& str)
{
if (!str.length()) {
return BPMF();
}
string pinyin = str;
transform(pinyin.begin(), pinyin.end(), pinyin.begin(), ::tolower);
BPMF::Component firstComponent = 0;
BPMF::Component secondComponent = 0;
BPMF::Component thirdComponent = 0;
BPMF::Component toneComponent = 0;
// lookup consonants and consume them
bool independentConsonant = false;
// the y exceptions fist
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yuan")) { secondComponent = BPMF::UE; thirdComponent = BPMF::AN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ying")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yung")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yong")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yue")) { secondComponent = BPMF::UE; thirdComponent = BPMF::E; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yun")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "you")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "yu")) { secondComponent = BPMF::UE; }
// try the first character
char c = pinyin.length() ? pinyin[0] : 0;
switch (c) {
case 'b': firstComponent = BPMF::B; pinyin = pinyin.substr(1); break;
case 'p': firstComponent = BPMF::P; pinyin = pinyin.substr(1); break;
case 'm': firstComponent = BPMF::M; pinyin = pinyin.substr(1); break;
case 'f': firstComponent = BPMF::F; pinyin = pinyin.substr(1); break;
case 'd': firstComponent = BPMF::D; pinyin = pinyin.substr(1); break;
case 't': firstComponent = BPMF::T; pinyin = pinyin.substr(1); break;
case 'n': firstComponent = BPMF::N; pinyin = pinyin.substr(1); break;
case 'l': firstComponent = BPMF::L; pinyin = pinyin.substr(1); break;
case 'g': firstComponent = BPMF::G; pinyin = pinyin.substr(1); break;
case 'k': firstComponent = BPMF::K; pinyin = pinyin.substr(1); break;
case 'h': firstComponent = BPMF::H; pinyin = pinyin.substr(1); break;
case 'j': firstComponent = BPMF::J; pinyin = pinyin.substr(1); break;
case 'q': firstComponent = BPMF::Q; pinyin = pinyin.substr(1); break;
case 'x': firstComponent = BPMF::X; pinyin = pinyin.substr(1); break;
// special hanlding for w and y
case 'w': secondComponent = BPMF::U; pinyin = pinyin.substr(1); break;
case 'y':
if (!secondComponent && !thirdComponent) {
secondComponent = BPMF::I;
}
pinyin = pinyin.substr(1);
break;
}
// then we try ZH, CH, SH, R, Z, C, S (in that order)
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "zh")) { firstComponent = BPMF::ZH; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ch")) { firstComponent = BPMF::CH; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "sh")) { firstComponent = BPMF::SH; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "r")) { firstComponent = BPMF::R; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "z")) { firstComponent = BPMF::Z; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "c")) { firstComponent = BPMF::C; independentConsonant = true; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "s")) { firstComponent = BPMF::S; independentConsonant = true; }
// consume exceptions first: (ien, in), (iou, iu), (uen, un), (veng, iong), (ven, vn), (uei, ui), ung
// but longer sequence takes precedence
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "veng")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iong")) { secondComponent = BPMF::UE; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ing")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ien")) { secondComponent = BPMF::I; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iou")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "uen")) { secondComponent = BPMF::U; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ven")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "uei")) { secondComponent = BPMF::U; thirdComponent = BPMF::EI; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ung")) {
// f exception
if (firstComponent == BPMF::F) {
thirdComponent = BPMF::ENG;
}
else {
secondComponent = BPMF::U; thirdComponent = BPMF::ENG;
}
}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ong")) {
// f exception
if (firstComponent == BPMF::F) {
thirdComponent = BPMF::ENG;
}
else {
secondComponent = BPMF::U;
thirdComponent = BPMF::ENG;
}
}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "un")) {
if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) {
secondComponent = BPMF::UE;
}
else {
secondComponent = BPMF::U;
}
thirdComponent = BPMF::EN;
}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "iu")) { secondComponent = BPMF::I; thirdComponent = BPMF::OU; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "in")) { secondComponent = BPMF::I; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "vn")) { secondComponent = BPMF::UE; thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ui")) { secondComponent = BPMF::U; thirdComponent = BPMF::EI; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ue"))
{
secondComponent = BPMF::UE; thirdComponent = BPMF::E;
}
#ifndef _MSC_VER
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ü")) { secondComponent = BPMF::UE; }
#else
else if (PinyinParseHelper::ConsumePrefix(pinyin, "\xc3\xbc")) { secondComponent = BPMF::UE; }
#endif
// then consume the middle component...
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "i")) { secondComponent = independentConsonant ? 0 : BPMF::I; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "u")) {
if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) {
secondComponent = BPMF::UE;
}
else {
secondComponent = BPMF::U;
}
}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "v")) { secondComponent = BPMF::UE; }
// the vowels, longer sequence takes precedence
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ang")) { thirdComponent = BPMF::ANG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "eng")) { thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "err")) { thirdComponent = BPMF::ERR; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ai")) { thirdComponent = BPMF::AI; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ei")) { thirdComponent = BPMF::EI; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ao")) { thirdComponent = BPMF::AO; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "ou")) { thirdComponent = BPMF::OU; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "an")) { thirdComponent = BPMF::AN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "en")) { thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "er")) { thirdComponent = BPMF::ERR; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "a")) { thirdComponent = BPMF::A; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "o")) { thirdComponent = BPMF::O; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "e")) {
if (secondComponent) {
thirdComponent = BPMF::E;
}
else {
thirdComponent = BPMF::ER;
}
}
// at last!
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pinyin, "1")) { toneComponent = BPMF::Tone1; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "2")) { toneComponent = BPMF::Tone2; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "3")) { toneComponent = BPMF::Tone3; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "4")) { toneComponent = BPMF::Tone4; }
else if (PinyinParseHelper::ConsumePrefix(pinyin, "5")) { toneComponent = BPMF::Tone5; }
return BPMF(firstComponent | secondComponent | thirdComponent | toneComponent);
}
const string BPMF::HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const
{
string consonant, middle, vowel, tone;
Component cc = consonantComponent(), mvc = middleVowelComponent(), vc = vowelComponent();
bool hasNoMVCOrVC = !(mvc || vc);
switch (cc) {
case B: consonant = "b"; break;
case P: consonant = "p"; break;
case M: consonant = "m"; break;
case F: consonant = "f"; break;
case D: consonant = "d"; break;
case T: consonant = "t"; break;
case N: consonant = "n"; break;
case L: consonant = "l"; break;
case G: consonant = "g"; break;
case K: consonant = "k"; break;
case H: consonant = "h"; break;
case J: consonant = "j"; if (hasNoMVCOrVC) middle = "i"; break;
case Q: consonant = "q"; if (hasNoMVCOrVC) middle = "i"; break;
case X: consonant = "x"; if (hasNoMVCOrVC) middle = "i"; break;
case ZH: consonant = "zh"; if (hasNoMVCOrVC) middle = "i"; break;
case CH: consonant = "ch"; if (hasNoMVCOrVC) middle = "i"; break;
case SH: consonant = "sh"; if (hasNoMVCOrVC) middle = "i"; break;
case R: consonant = "r"; if (hasNoMVCOrVC) middle = "i"; break;
case Z: consonant = "z"; if (hasNoMVCOrVC) middle = "i"; break;
case C: consonant = "c"; if (hasNoMVCOrVC) middle = "i"; break;
case S: consonant = "s"; if (hasNoMVCOrVC) middle = "i"; break;
}
switch (mvc) {
case I:
if (!cc) {
consonant = "y";
}
middle = (!vc || cc) ? "i" : "";
break;
case U:
if (!cc) {
consonant = "w";
}
middle = (!vc || cc) ? "u" : "";
break;
case UE:
if (!cc) {
consonant = "y";
}
if ((cc == N || cc == L) && vc != E) {
middle = useVForUUmlaut ? "v" : "ü";
}
else {
middle = "u";
}
break;
}
switch (vc) {
case A: vowel = "a"; break;
case O: vowel = "o"; break;
case ER: vowel = "e"; break;
case E: vowel = "e"; break;
case AI: vowel = "ai"; break;
case EI: vowel = "ei"; break;
case AO: vowel = "ao"; break;
case OU: vowel = "ou"; break;
case AN: vowel = "an"; break;
case EN: vowel = "en"; break;
case ANG: vowel = "ang"; break;
case ENG: vowel = "eng"; break;
case ERR: vowel = "er"; break;
}
// combination rules
// ueng -> ong, but note "weng"
if ((mvc == U || mvc == UE) && vc == ENG) {
middle = "";
vowel = (cc == J || cc == Q || cc == X) ? "iong" : ((!cc && mvc == U) ? "eng" : "ong");
}
// ien, uen, üen -> in, un, ün ; but note "wen", "yin" and "yun"
if (mvc && vc == EN) {
if (cc) {
vowel = "n";
}
else {
if (mvc == UE) {
vowel = "n"; // yun
}
else if (mvc == U) {
vowel = "en"; // wen
}
else {
vowel = "in"; // yin
}
}
}
// iou -> iu
if (cc && mvc == I && vc == OU) {
middle = "";
vowel = "iu";
}
// ieng -> ing
if (mvc == I && vc == ENG) {
middle = "";
vowel = "ing";
}
// uei -> ui
if (cc && mvc == U && vc == EI) {
middle = "";
vowel = "ui";
}
if (includesTone) {
switch (toneMarkerComponent()) {
case Tone2: tone = "2"; break;
case Tone3: tone = "3"; break;
case Tone4: tone = "4"; break;
case Tone5: tone = "5"; break;
}
}
return consonant + middle + vowel + tone;
}
const string BPMF::PHTString(bool includesTone) const
{
string consonant, middle, vowel, tone;
Component cc = consonantComponent(), mvc = middleVowelComponent(), vc = vowelComponent();
bool hasNoMVCOrVC = !(mvc || vc);
switch (cc) {
case B: consonant = "p"; break;
case P: consonant = "ph"; break;
case M: consonant = "m"; break;
case F: consonant = "f"; break;
case D: consonant = "t"; break;
case T: consonant = "th"; break;
case N: consonant = "n"; break;
case L: consonant = "l"; break;
case G: consonant = "k"; break;
case K: consonant = "kh"; break;
case H: consonant = "h"; break;
case J: consonant = "ch"; if (mvc != I) middle = "i"; break;
case Q: consonant = "chh"; if (mvc != I) middle = "i"; break;
case X: consonant = "hs"; if (mvc != I) middle = "i"; break;
case ZH: consonant = "ch"; if (hasNoMVCOrVC) middle = "i"; break;
case CH: consonant = "chh"; if (hasNoMVCOrVC) middle = "i"; break;
case SH: consonant = "sh"; if (hasNoMVCOrVC) middle = "i"; break;
case R: consonant = "r"; if (hasNoMVCOrVC) middle = "i"; break;
case Z: consonant = "ts"; if (hasNoMVCOrVC) middle = "i"; break;
case C: consonant = "tsh"; if (hasNoMVCOrVC) middle = "i"; break;
case S: consonant = "s"; if (hasNoMVCOrVC) middle = "i"; break;
}
switch (mvc) {
case I:
middle = "i";
break;
case U:
middle = "u";
break;
case UE:
middle = "uu";
break;
}
switch (vc) {
case A: vowel = "a"; break;
case O: vowel = "o"; break;
case ER: vowel = "e"; break;
case E: vowel = (!(cc || mvc)) ? "eh" : "e"; break;
case AI: vowel = "ai"; break;
case EI: vowel = "ei"; break;
case AO: vowel = "ao"; break;
case OU: vowel = "ou"; break;
case AN: vowel = "an"; break;
case EN: vowel = "en"; break;
case ANG: vowel = "ang"; break;
case ENG: vowel = "eng"; break;
case ERR: vowel = "err"; break;
}
// ieng -> ing
if (mvc == I && vc == ENG) {
middle = "";
vowel = "ing";
}
// zh/ch + i without third component -> append h
if (cc == BPMF::ZH || cc == BPMF::CH) {
if (!mvc && !vc) {
vowel = "h";
}
}
if (includesTone) {
switch (toneMarkerComponent()) {
case Tone2: tone = "2"; break;
case Tone3: tone = "3"; break;
case Tone4: tone = "4"; break;
case Tone5: tone = "5"; break;
}
}
return consonant + middle + vowel + tone;
}
const BPMF BPMF::FromPHT(const string& str)
{
if (!str.length()) {
return BPMF();
}
string pht = str;
transform(pht.begin(), pht.end(), pht.begin(), ::tolower);
BPMF::Component firstComponent = 0;
BPMF::Component secondComponent = 0;
BPMF::Component thirdComponent = 0;
BPMF::Component toneComponent = 0;
#define IF_CONSUME1(k, v) else if (PinyinParseHelper::ConsumePrefix(pht, k)) { firstComponent = v; }
// consume the first part
if (0) {}
IF_CONSUME1("ph", BPMF::P)
IF_CONSUME1("p", BPMF::B)
IF_CONSUME1("m", BPMF::M)
IF_CONSUME1("f", BPMF::F)
IF_CONSUME1("th", BPMF::T)
IF_CONSUME1("n", BPMF::N)
IF_CONSUME1("l", BPMF::L)
IF_CONSUME1("kh", BPMF::K)
IF_CONSUME1("k", BPMF::G)
IF_CONSUME1("chh", BPMF::Q)
IF_CONSUME1("ch", BPMF::J)
IF_CONSUME1("hs", BPMF::X)
IF_CONSUME1("sh", BPMF::SH)
IF_CONSUME1("r", BPMF::R)
IF_CONSUME1("tsh", BPMF::C)
IF_CONSUME1("ts", BPMF::Z)
IF_CONSUME1("s", BPMF::S)
IF_CONSUME1("t", BPMF::D)
IF_CONSUME1("h", BPMF::H)
#define IF_CONSUME2(k, v) else if (PinyinParseHelper::ConsumePrefix(pht, k)) { secondComponent = v; }
// consume the second part
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pht, "ing")) { secondComponent = BPMF::I; thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pht, "ih")) {
if (firstComponent == BPMF::J) {
firstComponent = BPMF::ZH;
}
else if (firstComponent == BPMF::Q) {
firstComponent = BPMF::CH;
}
}
IF_CONSUME2("i", BPMF::I)
IF_CONSUME2("uu", BPMF::UE)
IF_CONSUME2("u", BPMF::U)
#undef IF_CONSUME1
#undef IF_CONSUME2
// the vowels, longer sequence takes precedence
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pht, "ang")) { thirdComponent = BPMF::ANG; }
else if (PinyinParseHelper::ConsumePrefix(pht, "eng")) { thirdComponent = BPMF::ENG; }
else if (PinyinParseHelper::ConsumePrefix(pht, "err")) { thirdComponent = BPMF::ERR; }
else if (PinyinParseHelper::ConsumePrefix(pht, "ai")) { thirdComponent = BPMF::AI; }
else if (PinyinParseHelper::ConsumePrefix(pht, "ei")) { thirdComponent = BPMF::EI; }
else if (PinyinParseHelper::ConsumePrefix(pht, "ao")) { thirdComponent = BPMF::AO; }
else if (PinyinParseHelper::ConsumePrefix(pht, "ou")) { thirdComponent = BPMF::OU; }
else if (PinyinParseHelper::ConsumePrefix(pht, "an")) { thirdComponent = BPMF::AN; }
else if (PinyinParseHelper::ConsumePrefix(pht, "en")) { thirdComponent = BPMF::EN; }
else if (PinyinParseHelper::ConsumePrefix(pht, "er")) { thirdComponent = BPMF::ERR; }
else if (PinyinParseHelper::ConsumePrefix(pht, "a")) { thirdComponent = BPMF::A; }
else if (PinyinParseHelper::ConsumePrefix(pht, "o")) { thirdComponent = BPMF::O; }
else if (PinyinParseHelper::ConsumePrefix(pht, "eh")) { thirdComponent = BPMF::E; }
else if (PinyinParseHelper::ConsumePrefix(pht, "e")) {
if (secondComponent) {
thirdComponent = BPMF::E;
}
else {
thirdComponent = BPMF::ER;
}
}
// fix ch/chh mappings
Component corresponding = 0;
if (firstComponent == BPMF::J) {
corresponding = BPMF::ZH;
}
else if (firstComponent == BPMF::Q) {
corresponding = BPMF::CH;
}
if (corresponding) {
if (secondComponent == BPMF::I && !thirdComponent) {
// if the second component is I and there's no third component, we use the corresponding part
// firstComponent = corresponding;
}
else if (secondComponent == BPMF::U) {
// if second component is U, we use the corresponding part
firstComponent = corresponding;
}
else if (!secondComponent) {
// if there's no second component, it must be a corresponding part
firstComponent = corresponding;
}
}
if (secondComponent == BPMF::I) {
// fixes a few impossible occurances
switch(firstComponent) {
case BPMF::ZH:
case BPMF::CH:
case BPMF::SH:
case BPMF::R:
case BPMF::Z:
case BPMF::C:
case BPMF::S:
secondComponent = 0;
}
}
// at last!
if (0) {}
else if (PinyinParseHelper::ConsumePrefix(pht, "1")) { toneComponent = BPMF::Tone1; }
else if (PinyinParseHelper::ConsumePrefix(pht, "2")) { toneComponent = BPMF::Tone2; }
else if (PinyinParseHelper::ConsumePrefix(pht, "3")) { toneComponent = BPMF::Tone3; }
else if (PinyinParseHelper::ConsumePrefix(pht, "4")) { toneComponent = BPMF::Tone4; }
else if (PinyinParseHelper::ConsumePrefix(pht, "5")) { toneComponent = BPMF::Tone5; }
return BPMF(firstComponent | secondComponent | thirdComponent | toneComponent);
}
const BPMF BPMF::FromComposedString(const string& str)
{
BPMF syllable;
vector<string> components = OVUTF8Helper::SplitStringByCodePoint(str);
for (vector<string>::iterator iter = components.begin() ; iter != components.end() ; ++iter) {
const map<string, BPMF::Component>& charToComp = BopomofoCharacterMap::SharedInstance().characterToComponent;
map<string, BPMF::Component>::const_iterator result = charToComp.find(*iter);
if (result != charToComp.end())
syllable += BPMF((*result).second);
}
return syllable;
}
const string BPMF::composedString() const
{
string result;
#define APPEND(c) if (m_syllable & c) result += (*BopomofoCharacterMap::SharedInstance().componentToCharacter.find(m_syllable & c)).second
APPEND(ConsonantMask);
APPEND(MiddleVowelMask);
APPEND(VowelMask);
APPEND(ToneMarkerMask);
#undef APPEND
return result;
}
BopomofoCharacterMap* BopomofoCharacterMap::c_map = 0;
const BopomofoCharacterMap& BopomofoCharacterMap::SharedInstance()
{
if (!c_map)
c_map = new BopomofoCharacterMap();
return *c_map;
}
BopomofoCharacterMap::BopomofoCharacterMap()
{
#ifndef _MSC_VER
characterToComponent[""] = BPMF::B;
characterToComponent[""] = BPMF::P;
characterToComponent[""] = BPMF::M;
characterToComponent[""] = BPMF::F;
characterToComponent[""] = BPMF::D;
characterToComponent[""] = BPMF::T;
characterToComponent[""] = BPMF::N;
characterToComponent[""] = BPMF::L;
characterToComponent[""] = BPMF::K;
characterToComponent[""] = BPMF::G;
characterToComponent[""] = BPMF::H;
characterToComponent[""] = BPMF::J;
characterToComponent[""] = BPMF::Q;
characterToComponent[""] = BPMF::X;
characterToComponent[""] = BPMF::ZH;
characterToComponent[""] = BPMF::CH;
characterToComponent[""] = BPMF::SH;
characterToComponent[""] = BPMF::R;
characterToComponent[""] = BPMF::Z;
characterToComponent[""] = BPMF::C;
characterToComponent[""] = BPMF::S;
characterToComponent[""] = BPMF::I;
characterToComponent[""] = BPMF::U;
characterToComponent[""] = BPMF::UE;
characterToComponent[""] = BPMF::A;
characterToComponent[""] = BPMF::O;
characterToComponent[""] = BPMF::ER;
characterToComponent[""] = BPMF::E;
characterToComponent[""] = BPMF::AI;
characterToComponent[""] = BPMF::EI;
characterToComponent[""] = BPMF::AO;
characterToComponent[""] = BPMF::OU;
characterToComponent[""] = BPMF::AN;
characterToComponent[""] = BPMF::EN;
characterToComponent[""] = BPMF::ANG;
characterToComponent[""] = BPMF::ENG;
characterToComponent[""] = BPMF::ERR;
characterToComponent["ˊ"] = BPMF::Tone2;
characterToComponent["ˇ"] = BPMF::Tone3;
characterToComponent["ˋ"] = BPMF::Tone4;
characterToComponent["˙"] = BPMF::Tone5;
#else
characterToComponent["\xe3\x84\x85"] = BPMF::B;
characterToComponent["\xe3\x84\x86"] = BPMF::P;
characterToComponent["\xe3\x84\x87"] = BPMF::M;
characterToComponent["\xe3\x84\x88"] = BPMF::F;
characterToComponent["\xe3\x84\x89"] = BPMF::D;
characterToComponent["\xe3\x84\x8a"] = BPMF::T;
characterToComponent["\xe3\x84\x8b"] = BPMF::N;
characterToComponent["\xe3\x84\x8c"] = BPMF::L;
characterToComponent["\xe3\x84\x8e"] = BPMF::K;
characterToComponent["\xe3\x84\x8d"] = BPMF::G;
characterToComponent["\xe3\x84\x8f"] = BPMF::H;
characterToComponent["\xe3\x84\x90"] = BPMF::J;
characterToComponent["\xe3\x84\x91"] = BPMF::Q;
characterToComponent["\xe3\x84\x92"] = BPMF::X;
characterToComponent["\xe3\x84\x93"] = BPMF::ZH;
characterToComponent["\xe3\x84\x94"] = BPMF::CH;
characterToComponent["\xe3\x84\x95"] = BPMF::SH;
characterToComponent["\xe3\x84\x96"] = BPMF::R;
characterToComponent["\xe3\x84\x97"] = BPMF::Z;
characterToComponent["\xe3\x84\x98"] = BPMF::C;
characterToComponent["\xe3\x84\x99"] = BPMF::S;
characterToComponent["\xe3\x84\xa7"] = BPMF::I;
characterToComponent["\xe3\x84\xa8"] = BPMF::U;
characterToComponent["\xe3\x84\xa9"] = BPMF::UE;
characterToComponent["\xe3\x84\x9a"] = BPMF::A;
characterToComponent["\xe3\x84\x9b"] = BPMF::O;
characterToComponent["\xe3\x84\x9c"] = BPMF::ER;
characterToComponent["\xe3\x84\x9d"] = BPMF::E;
characterToComponent["\xe3\x84\x9e"] = BPMF::AI;
characterToComponent["\xe3\x84\x9f"] = BPMF::EI;
characterToComponent["\xe3\x84\xa0"] = BPMF::AO;
characterToComponent["\xe3\x84\xa1"] = BPMF::OU;
characterToComponent["\xe3\x84\xa2"] = BPMF::AN;
characterToComponent["\xe3\x84\xa3"] = BPMF::EN;
characterToComponent["\xe3\x84\xa4"] = BPMF::ANG;
characterToComponent["\xe3\x84\xa5"] = BPMF::ENG;
characterToComponent["\xe3\x84\xa6"] = BPMF::ERR;
characterToComponent["\xcb\x8a"] = BPMF::Tone2;
characterToComponent["\xcb\x87"] = BPMF::Tone3;
characterToComponent["\xcb\x8b"] = BPMF::Tone4;
characterToComponent["\xcb\x99"] = BPMF::Tone5;
#endif
for (map<string, BPMF::Component>::iterator iter = characterToComponent.begin() ; iter != characterToComponent.end() ; ++iter)
componentToCharacter[(*iter).second] = (*iter).first;
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_StandardLayout = 0;
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_ETenLayout = 0;
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_HsuLayout = 0;
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_ETen26Layout = 0;
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::c_HanyuPinyinLayout = 0;
void BopomofoKeyboardLayout::FinalizeLayouts()
{
#define FL(x) if (x) { delete x; } x = 0
FL(c_StandardLayout);
FL(c_ETen26Layout);
FL(c_HsuLayout);
FL(c_ETen26Layout);
FL(c_HanyuPinyinLayout);
#undef FL
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::LayoutForName(const string& name)
{
if (OVWildcard::Match(name, "standard"))
return StandardLayout();
if (OVWildcard::Match(name, "eten"))
return ETenLayout();
if (OVWildcard::Match(name, "hsu"))
return HsuLayout();
if (OVWildcard::Match(name, "eten26"))
return ETen26Layout();
if (OVWildcard::Match(name, "hanyupinyin") || OVWildcard::Match(name, "hanyu pinyin") || OVWildcard::Match(name, "hanyu-pinyin") || OVWildcard::Match(name, "pinyin"))
return HanyuPinyinLayout();
return 0;
}
#define ASSIGNKEY1(m, vec, k, val) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val), vec)
#define ASSIGNKEY2(m, vec, k, val1, val2) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), vec)
#define ASSIGNKEY3(m, vec, k, val1, val2, val3) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), vec.push_back((BPMF::Component)val3), vec)
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::StandardLayout()
{
if (!c_StandardLayout) {
vector<BPMF::Component> vec;
BopomofoKeyToComponentMap ktcm;
ASSIGNKEY1(ktcm, vec, '1', BPMF::B);
ASSIGNKEY1(ktcm, vec, 'q', BPMF::P);
ASSIGNKEY1(ktcm, vec, 'a', BPMF::M);
ASSIGNKEY1(ktcm, vec, 'z', BPMF::F);
ASSIGNKEY1(ktcm, vec, '2', BPMF::D);
ASSIGNKEY1(ktcm, vec, 'w', BPMF::T);
ASSIGNKEY1(ktcm, vec, 's', BPMF::N);
ASSIGNKEY1(ktcm, vec, 'x', BPMF::L);
ASSIGNKEY1(ktcm, vec, 'e', BPMF::G);
ASSIGNKEY1(ktcm, vec, 'd', BPMF::K);
ASSIGNKEY1(ktcm, vec, 'c', BPMF::H);
ASSIGNKEY1(ktcm, vec, 'r', BPMF::J);
ASSIGNKEY1(ktcm, vec, 'f', BPMF::Q);
ASSIGNKEY1(ktcm, vec, 'v', BPMF::X);
ASSIGNKEY1(ktcm, vec, '5', BPMF::ZH);
ASSIGNKEY1(ktcm, vec, 't', BPMF::CH);
ASSIGNKEY1(ktcm, vec, 'g', BPMF::SH);
ASSIGNKEY1(ktcm, vec, 'b', BPMF::R);
ASSIGNKEY1(ktcm, vec, 'y', BPMF::Z);
ASSIGNKEY1(ktcm, vec, 'h', BPMF::C);
ASSIGNKEY1(ktcm, vec, 'n', BPMF::S);
ASSIGNKEY1(ktcm, vec, 'u', BPMF::I);
ASSIGNKEY1(ktcm, vec, 'j', BPMF::U);
ASSIGNKEY1(ktcm, vec, 'm', BPMF::UE);
ASSIGNKEY1(ktcm, vec, '8', BPMF::A);
ASSIGNKEY1(ktcm, vec, 'i', BPMF::O);
ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER);
ASSIGNKEY1(ktcm, vec, ',', BPMF::E);
ASSIGNKEY1(ktcm, vec, '9', BPMF::AI);
ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI);
ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO);
ASSIGNKEY1(ktcm, vec, '.', BPMF::OU);
ASSIGNKEY1(ktcm, vec, '0', BPMF::AN);
ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN);
ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG);
ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG);
ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR);
ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3);
ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4);
ASSIGNKEY1(ktcm, vec, '6', BPMF::Tone2);
ASSIGNKEY1(ktcm, vec, '7', BPMF::Tone5);
c_StandardLayout = new BopomofoKeyboardLayout(ktcm, "Standard");
}
return c_StandardLayout;
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETenLayout()
{
if (!c_ETenLayout) {
vector<BPMF::Component> vec;
BopomofoKeyToComponentMap ktcm;
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
ASSIGNKEY1(ktcm, vec, 'p', BPMF::P);
ASSIGNKEY1(ktcm, vec, 'm', BPMF::M);
ASSIGNKEY1(ktcm, vec, 'f', BPMF::F);
ASSIGNKEY1(ktcm, vec, 'd', BPMF::D);
ASSIGNKEY1(ktcm, vec, 't', BPMF::T);
ASSIGNKEY1(ktcm, vec, 'n', BPMF::N);
ASSIGNKEY1(ktcm, vec, 'l', BPMF::L);
ASSIGNKEY1(ktcm, vec, 'v', BPMF::G);
ASSIGNKEY1(ktcm, vec, 'k', BPMF::K);
ASSIGNKEY1(ktcm, vec, 'h', BPMF::H);
ASSIGNKEY1(ktcm, vec, 'g', BPMF::J);
ASSIGNKEY1(ktcm, vec, '7', BPMF::Q);
ASSIGNKEY1(ktcm, vec, 'c', BPMF::X);
ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH);
ASSIGNKEY1(ktcm, vec, '.', BPMF::CH);
ASSIGNKEY1(ktcm, vec, '/', BPMF::SH);
ASSIGNKEY1(ktcm, vec, 'j', BPMF::R);
ASSIGNKEY1(ktcm, vec, ';', BPMF::Z);
ASSIGNKEY1(ktcm, vec, '\'', BPMF::C);
ASSIGNKEY1(ktcm, vec, 's', BPMF::S);
ASSIGNKEY1(ktcm, vec, 'e', BPMF::I);
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
ASSIGNKEY1(ktcm, vec, 'a', BPMF::A);
ASSIGNKEY1(ktcm, vec, 'o', BPMF::O);
ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER);
ASSIGNKEY1(ktcm, vec, 'w', BPMF::E);
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
ASSIGNKEY1(ktcm, vec, 'q', BPMF::EI);
ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO);
ASSIGNKEY1(ktcm, vec, 'y', BPMF::OU);
ASSIGNKEY1(ktcm, vec, '8', BPMF::AN);
ASSIGNKEY1(ktcm, vec, '9', BPMF::EN);
ASSIGNKEY1(ktcm, vec, '0', BPMF::ANG);
ASSIGNKEY1(ktcm, vec, '-', BPMF::ENG);
ASSIGNKEY1(ktcm, vec, '=', BPMF::ERR);
ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2);
ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3);
ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4);
ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5);
c_ETenLayout = new BopomofoKeyboardLayout(ktcm, "ETen");
}
return c_ETenLayout;
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HsuLayout()
{
if (!c_HsuLayout) {
vector<BPMF::Component> vec;
BopomofoKeyToComponentMap ktcm;
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
ASSIGNKEY1(ktcm, vec, 'p', BPMF::P);
ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN);
ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone3);
ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone2);
ASSIGNKEY1(ktcm, vec, 't', BPMF::T);
ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN);
ASSIGNKEY3(ktcm, vec, 'l', BPMF::L, BPMF::ENG, BPMF::ERR);
ASSIGNKEY2(ktcm, vec, 'g', BPMF::G, BPMF::ER);
ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::ANG);
ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::O);
ASSIGNKEY3(ktcm, vec, 'j', BPMF::J, BPMF::ZH, BPMF::Tone4);
ASSIGNKEY2(ktcm, vec, 'v', BPMF::Q, BPMF::CH);
ASSIGNKEY2(ktcm, vec, 'c', BPMF::X, BPMF::SH);
ASSIGNKEY1(ktcm, vec, 'r', BPMF::R);
ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z);
ASSIGNKEY2(ktcm, vec, 'a', BPMF::C, BPMF::EI);
ASSIGNKEY2(ktcm, vec, 's', BPMF::S, BPMF::Tone5);
ASSIGNKEY2(ktcm, vec, 'e', BPMF::I, BPMF::E);
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
ASSIGNKEY1(ktcm, vec, 'y', BPMF::A);
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
ASSIGNKEY1(ktcm, vec, 'w', BPMF::AO);
ASSIGNKEY1(ktcm, vec, 'o', BPMF::OU);
c_HsuLayout = new BopomofoKeyboardLayout(ktcm, "Hsu");
}
return c_HsuLayout;
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::ETen26Layout()
{
if (!c_ETen26Layout) {
vector<BPMF::Component> vec;
BopomofoKeyToComponentMap ktcm;
ASSIGNKEY1(ktcm, vec, 'b', BPMF::B);
ASSIGNKEY2(ktcm, vec, 'p', BPMF::P, BPMF::OU);
ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN);
ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone2);
ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone5);
ASSIGNKEY2(ktcm, vec, 't', BPMF::T, BPMF::ANG);
ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN);
ASSIGNKEY2(ktcm, vec, 'l', BPMF::L, BPMF::ENG);
ASSIGNKEY2(ktcm, vec, 'v', BPMF::G, BPMF::Q);
ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::Tone4);
ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::ERR);
ASSIGNKEY2(ktcm, vec, 'g', BPMF::ZH, BPMF::J);
ASSIGNKEY2(ktcm, vec, 'c', BPMF::SH, BPMF::X);
ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH);
ASSIGNKEY2(ktcm, vec, 'j', BPMF::R, BPMF::Tone3);
ASSIGNKEY2(ktcm, vec, 'q', BPMF::Z, BPMF::EI);
ASSIGNKEY2(ktcm, vec, 'w', BPMF::C, BPMF::E);
ASSIGNKEY1(ktcm, vec, 's', BPMF::S);
ASSIGNKEY1(ktcm, vec, 'e', BPMF::I);
ASSIGNKEY1(ktcm, vec, 'x', BPMF::U);
ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE);
ASSIGNKEY1(ktcm, vec, 'a', BPMF::A);
ASSIGNKEY1(ktcm, vec, 'o', BPMF::O);
ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER);
ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI);
ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO);
c_ETen26Layout = new BopomofoKeyboardLayout(ktcm, "ETen26");
}
return c_ETen26Layout;
}
const BopomofoKeyboardLayout* BopomofoKeyboardLayout::HanyuPinyinLayout()
{
if (!c_HanyuPinyinLayout) {
BopomofoKeyToComponentMap ktcm;
c_HanyuPinyinLayout = new BopomofoKeyboardLayout(ktcm, "HanyuPinyin");
}
return c_HanyuPinyinLayout;
}
} // namespace Mandarin
} // namespace Formosa

View File

@ -0,0 +1,605 @@
//
// Mandarin.h
//
// Copyright (c) 2006-2010 Lukhnos D. Liu (http://lukhnos.org)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef Mandarin_h
#define Mandarin_h
#include <iostream>
#include <string>
#include <vector>
#include <map>
namespace Formosa {
namespace Mandarin {
using namespace std;
class BopomofoSyllable {
public:
typedef unsigned int Component;
BopomofoSyllable(Component syllable = 0)
: m_syllable(syllable)
{
}
BopomofoSyllable(const BopomofoSyllable& another)
: m_syllable(another.m_syllable)
{
}
~BopomofoSyllable()
{
}
BopomofoSyllable& operator=(const BopomofoSyllable& another)
{
m_syllable = another.m_syllable;
return *this;
}
// takes the ASCII-form, "v"-tolerant, TW-style Hanyu Pinyin (fong, pong, bong acceptable)
static const BopomofoSyllable FromHanyuPinyin(const string& str);
// TO DO: Support accented vowels
const string HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const;
// const string HanyuPinyinString(bool includesTone, bool useVForUUmlaut, bool composeAccentedVowel) const;
// PHT = Pai-hua-tsi
static const BopomofoSyllable FromPHT(const string& str);
const string PHTString(bool includesTone) const;
static const BopomofoSyllable FromComposedString(const string& str);
const string composedString() const;
void clear()
{
m_syllable = 0;
}
bool isEmpty() const
{
return !m_syllable;
}
bool hasConsonant() const
{
return !!(m_syllable & ConsonantMask);
}
bool hasMiddleVowel() const
{
return !!(m_syllable & MiddleVowelMask);
}
bool hasVowel() const
{
return !!(m_syllable & VowelMask);
}
bool hasToneMarker() const
{
return !!(m_syllable & ToneMarkerMask);
}
Component consonantComponent() const
{
return m_syllable & ConsonantMask;
}
Component middleVowelComponent() const
{
return m_syllable & MiddleVowelMask;
}
Component vowelComponent() const
{
return m_syllable & VowelMask;
}
Component toneMarkerComponent() const
{
return m_syllable & ToneMarkerMask;
}
bool operator==(const BopomofoSyllable& another) const
{
return m_syllable == another.m_syllable;
}
bool operator!=(const BopomofoSyllable& another) const
{
return m_syllable != another.m_syllable;
}
bool isOverlappingWith(const BopomofoSyllable& another) const
{
#define IOW_SAND(mask) ((m_syllable & mask) && (another.m_syllable & mask))
return IOW_SAND(ConsonantMask) || IOW_SAND(MiddleVowelMask) || IOW_SAND(VowelMask) || IOW_SAND(ToneMarkerMask);
#undef IOW_SAND
}
// consonants J, Q, X all require the existence of vowel I or UE
bool belongsToJQXClass() const
{
Component consonant = m_syllable & ConsonantMask;
return (consonant == J || consonant == Q || consonant == X);
}
// zi, ci, si, chi, chi, shi, ri
bool belongsToZCSRClass() const
{
Component consonant = m_syllable & ConsonantMask;
return (consonant >= ZH && consonant <= S);
}
Component maskType() const
{
Component mask = 0;
mask |= (m_syllable & ConsonantMask) ? ConsonantMask : 0;
mask |= (m_syllable & MiddleVowelMask) ? MiddleVowelMask : 0;
mask |= (m_syllable & VowelMask) ? VowelMask : 0;
mask |= (m_syllable & ToneMarkerMask) ? ToneMarkerMask : 0;
return mask;
}
const BopomofoSyllable operator+(const BopomofoSyllable& another) const
{
Component newSyllable = m_syllable;
#define OP_SOVER(mask) if (another.m_syllable & mask) newSyllable = (newSyllable & ~mask) | (another.m_syllable & mask)
OP_SOVER(ConsonantMask);
OP_SOVER(MiddleVowelMask);
OP_SOVER(VowelMask);
OP_SOVER(ToneMarkerMask);
#undef OP_SOVER
return BopomofoSyllable(newSyllable);
}
BopomofoSyllable& operator+=(const BopomofoSyllable& another)
{
#define OPE_SOVER(mask) if (another.m_syllable & mask) m_syllable = (m_syllable & ~mask) | (another.m_syllable & mask)
OPE_SOVER(ConsonantMask);
OPE_SOVER(MiddleVowelMask);
OPE_SOVER(VowelMask);
OPE_SOVER(ToneMarkerMask);
#undef OPE_SOVER
return *this;
}
short absoluteOrder() const
{
// turn BPMF syllable into a 4*14*4*22 number
return (short)(m_syllable & ConsonantMask) +
(short)((m_syllable & MiddleVowelMask) >> 5) * 22 +
(short)((m_syllable & VowelMask) >> 7) * 22 * 4 +
(short)((m_syllable & ToneMarkerMask) >> 11) * 22 * 4 * 14;
}
const string absoluteOrderString() const
{
// 5*14*4*22 = 6160, we use a 79*79 encoding to represent that
short order = absoluteOrder();
char low = 48 + (char)(order % 79);
char high = 48 + (char)(order / 79);
string result(2, ' ');
result[0] = low;
result[1] = high;
return result;
}
static BopomofoSyllable FromAbsoluteOrder(short order)
{
return BopomofoSyllable(
(order % 22) |
((order / 22) % 4) << 5 |
((order / (22 * 4)) % 14) << 7 |
((order / (22 * 4 * 14)) % 5) << 11
);
}
static BopomofoSyllable FromAbsoluteOrderString(const string& str)
{
if (str.length() != 2)
return BopomofoSyllable();
return FromAbsoluteOrder((short)(str[1] - 48) * 79 + (short)(str[0] - 48));
}
friend ostream& operator<<(ostream& stream, const BopomofoSyllable& syllable);
static const Component
ConsonantMask = 0x001f, // 0000 0000 0001 1111, 21 consonants
MiddleVowelMask = 0x0060, // 0000 0000 0110 0000, 3 middle vowels
VowelMask = 0x0780, // 0000 0111 1000 0000, 13 vowels
ToneMarkerMask = 0x3800, // 0011 1000 0000 0000, 5 tones (tone1 = 0x00)
B = 0x0001, P = 0x0002, M = 0x0003, F = 0x0004,
D = 0x0005, T = 0x0006, N = 0x0007, L = 0x0008,
G = 0x0009, K = 0x000a, H = 0x000b,
J = 0x000c, Q = 0x000d, X = 0x000e,
ZH = 0x000f, CH = 0x0010, SH = 0x0011, R = 0x0012,
Z = 0x0013, C = 0x0014, S = 0x0015,
I = 0x0020, U = 0x0040, UE = 0x0060, // ue = u umlaut (we use the German convention here as an ersatz to the /ju:/ sound)
A = 0x0080, O = 0x0100, ER = 0x0180, E = 0x0200,
AI = 0x0280, EI = 0x0300, AO = 0x0380, OU = 0x0400,
AN = 0x0480, EN = 0x0500, ANG = 0x0580, ENG = 0x0600,
ERR = 0x0680,
Tone1 = 0x0000, Tone2 = 0x0800, Tone3 = 0x1000, Tone4 = 0x1800, Tone5 = 0x2000;
protected:
Component m_syllable;
};
inline ostream& operator<<(ostream& stream, const BopomofoSyllable& syllable)
{
stream << syllable.composedString();
return stream;
}
typedef BopomofoSyllable BPMF;
typedef map<char, vector<BPMF::Component> > BopomofoKeyToComponentMap;
typedef map<BPMF::Component, char> BopomofoComponentToKeyMap;
class BopomofoKeyboardLayout {
public:
static void FinalizeLayouts();
static const BopomofoKeyboardLayout* StandardLayout();
static const BopomofoKeyboardLayout* ETenLayout();
static const BopomofoKeyboardLayout* HsuLayout();
static const BopomofoKeyboardLayout* ETen26Layout();
static const BopomofoKeyboardLayout* HanyuPinyinLayout();
// recognizes (case-insensitive): standard, eten, hsu, eten26
static const BopomofoKeyboardLayout* LayoutForName(const string& name);
BopomofoKeyboardLayout(const BopomofoKeyToComponentMap& ktcm, const string& name)
: m_keyToComponent(ktcm)
, m_name(name)
{
for (BopomofoKeyToComponentMap::const_iterator miter = m_keyToComponent.begin() ; miter != m_keyToComponent.end() ; ++miter)
for (vector<BPMF::Component>::const_iterator viter = (*miter).second.begin() ; viter != (*miter).second.end() ; ++viter)
m_componentToKey[*viter] = (*miter).first;
}
const string name() const
{
return m_name;
}
char componentToKey(BPMF::Component component) const
{
BopomofoComponentToKeyMap::const_iterator iter = m_componentToKey.find(component);
return (iter == m_componentToKey.end()) ? 0 : (*iter).second;
}
const vector<BPMF::Component> keyToComponents(char key) const
{
BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key);
return (iter == m_keyToComponent.end()) ? vector<BPMF::Component>() : (*iter).second;
}
const string keySequenceFromSyllable(BPMF syllable) const
{
string sequence;
BPMF::Component c;
char k;
#define STKS_COMBINE(component) if ((c = component)) { if ((k = componentToKey(c))) sequence += string(1, k); }
STKS_COMBINE(syllable.consonantComponent());
STKS_COMBINE(syllable.middleVowelComponent());
STKS_COMBINE(syllable.vowelComponent());
STKS_COMBINE(syllable.toneMarkerComponent());
#undef STKS_COMBINE
return sequence;
}
const BPMF syllableFromKeySequence(const string& sequence) const
{
BPMF syllable;
for (string::const_iterator iter = sequence.begin() ; iter != sequence.end() ; ++iter)
{
bool beforeSeqHasIorUE = sequenceContainsIorUE(sequence.begin(), iter);
bool aheadSeqHasIorUE = sequenceContainsIorUE(iter + 1, sequence.end());
vector<BPMF::Component> components = keyToComponents(*iter);
if (!components.size())
continue;
if (components.size() == 1) {
syllable += BPMF(components[0]);
continue;
}
BPMF head = BPMF(components[0]);
BPMF follow = BPMF(components[1]);
BPMF ending = components.size() > 2 ? BPMF(components[2]) : follow;
// apply the I/UE + E rule
if (head.vowelComponent() == BPMF::E && follow.vowelComponent() != BPMF::E)
{
syllable += beforeSeqHasIorUE ? head : follow;
continue;
}
if (head.vowelComponent() != BPMF::E && follow.vowelComponent() == BPMF::E)
{
syllable += beforeSeqHasIorUE ? follow : head;
continue;
}
// apply the J/Q/X + I/UE rule, only two components are allowed in the components vector here
if (head.belongsToJQXClass() && !follow.belongsToJQXClass()) {
if (!syllable.isEmpty()) {
if (ending != follow)
syllable += ending;
}
else {
syllable += aheadSeqHasIorUE ? head : follow;
}
continue;
}
if (!head.belongsToJQXClass() && follow.belongsToJQXClass()) {
if (!syllable.isEmpty()) {
if (ending != follow)
syllable += ending;
}
else {
syllable += aheadSeqHasIorUE ? follow : head;
}
continue;
}
// the nasty issue of only one char in the buffer
if (iter == sequence.begin() && iter + 1 == sequence.end()) {
if (head.hasVowel() || follow.hasToneMarker() || head.belongsToZCSRClass())
syllable += head;
else {
if (follow.hasVowel() || ending.hasToneMarker())
syllable += follow;
else
syllable += ending;
}
continue;
}
if (!(syllable.maskType() & head.maskType()) && !endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end())) {
syllable += head;
}
else {
if (endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end()) && head.belongsToZCSRClass() && syllable.isEmpty()) {
syllable += head;
}
else if (syllable.maskType() < follow.maskType()) {
syllable += follow;
}
else {
syllable += ending;
}
}
}
// heuristics for Hsu keyboard layout
if (this == HsuLayout()) {
// fix the left out L to ERR when it has sound, and GI, GUE -> JI, JUE
if (syllable.vowelComponent() == BPMF::ENG && !syllable.hasConsonant() && !syllable.hasMiddleVowel()) {
syllable += BPMF(BPMF::ERR);
}
else if (syllable.consonantComponent() == BPMF::G && (syllable.middleVowelComponent() == BPMF::I || syllable.middleVowelComponent() == BPMF::UE)) {
syllable += BPMF(BPMF::J);
}
}
return syllable;
}
protected:
bool endAheadOrAheadHasToneMarkKey(string::const_iterator ahead, string::const_iterator end) const
{
if (ahead == end)
return true;
char tone1 = componentToKey(BPMF::Tone1);
char tone2 = componentToKey(BPMF::Tone2);
char tone3 = componentToKey(BPMF::Tone3);
char tone4 = componentToKey(BPMF::Tone4);
char tone5 = componentToKey(BPMF::Tone5);
if (tone1)
if (*ahead == tone1) return true;
if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 || *ahead == tone5)
return true;
return false;
}
bool sequenceContainsIorUE(string::const_iterator start, string::const_iterator end) const
{
char iChar = componentToKey(BPMF::I);
char ueChar = componentToKey(BPMF::UE);
for (; start != end; ++start)
if (*start == iChar || *start == ueChar)
return true;
return false;
}
string m_name;
BopomofoKeyToComponentMap m_keyToComponent;
BopomofoComponentToKeyMap m_componentToKey;
static const BopomofoKeyboardLayout* c_StandardLayout;
static const BopomofoKeyboardLayout* c_ETenLayout;
static const BopomofoKeyboardLayout* c_HsuLayout;
static const BopomofoKeyboardLayout* c_ETen26Layout;
// this is essentially an empty layout, but we use pointer semantic to tell the differences--and pass on the responsibility to BopomofoReadingBuffer
static const BopomofoKeyboardLayout* c_HanyuPinyinLayout;
};
class BopomofoReadingBuffer {
public:
BopomofoReadingBuffer(const BopomofoKeyboardLayout* layout)
: m_layout(layout)
, m_pinyinMode(false)
{
if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) {
m_pinyinMode = true;
m_pinyinSequence = "";
}
}
void setKeyboardLayout(const BopomofoKeyboardLayout* layout)
{
m_layout = layout;
if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) {
m_pinyinMode = true;
m_pinyinSequence = "";
}
}
bool isValidKey(char k) const
{
if (!m_pinyinMode) {
return m_layout ? (m_layout->keyToComponents(k)).size() > 0 : false;
}
char lk = tolower(k);
if (lk >= 'a' && lk <= 'z') {
// if a tone marker is already in place
if (m_pinyinSequence.length()) {
char lastc = m_pinyinSequence[m_pinyinSequence.length() - 1];
if (lastc >= '2' && lastc <= '5') {
return false;
}
return true;
}
return true;
}
if (m_pinyinSequence.length() && (lk >= '2' && lk <= '5')) {
return true;
}
return false;
}
bool combineKey(char k)
{
if (!isValidKey(k))
return false;
if (m_pinyinMode) {
m_pinyinSequence += string(1, tolower(k));
m_syllable = BPMF::FromHanyuPinyin(m_pinyinSequence);
return true;
}
string sequence = m_layout->keySequenceFromSyllable(m_syllable) + string(1, k);
m_syllable = m_layout->syllableFromKeySequence(sequence);
return true;
}
void clear()
{
m_pinyinSequence.clear();
m_syllable.clear();
}
void backspace()
{
if (!m_layout)
return;
if (m_pinyinMode) {
if (m_pinyinSequence.length()) {
m_pinyinSequence = m_pinyinSequence.substr(0, m_pinyinSequence.length() - 1);
}
m_syllable = BPMF::FromHanyuPinyin(m_pinyinSequence);
return;
}
string sequence = m_layout->keySequenceFromSyllable(m_syllable);
if (sequence.length()) {
sequence = sequence.substr(0, sequence.length() - 1);
m_syllable = m_layout->syllableFromKeySequence(sequence);
}
}
bool isEmpty() const
{
return m_syllable.isEmpty();
}
const string composedString() const
{
if (m_pinyinMode) {
return m_pinyinSequence;
}
return m_syllable.composedString();
}
const BPMF syllable() const
{
return m_syllable;
}
const string standardLayoutQueryString() const
{
return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable(m_syllable);
}
const string absoluteOrderQueryString() const
{
return m_syllable.absoluteOrderString();
}
bool hasToneMarker() const
{
return m_syllable.hasToneMarker();
}
protected:
const BopomofoKeyboardLayout* m_layout;
BPMF m_syllable;
bool m_pinyinMode;
string m_pinyinSequence;
};
}
}
#endif

View File

@ -0,0 +1,49 @@
//
// OVAroundFilter.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVAroundFilter_h
#define OVAroundFilter_h
#if defined(__APPLE__)
#include <OpenVanilla/OVModule.h>
#else
#include "OVModule.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVAroundFilter : public OVModule {
public:
virtual bool isAroundFilter() const
{
return true;
}
};
};
#endif

View File

@ -0,0 +1,46 @@
//
// OVBase.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVBase_h
#define OVBase_h
#include <cstddef>
#include <string>
#include <vector>
namespace OpenVanilla {
using namespace std;
class OVBase {
public:
virtual ~OVBase()
{
}
};
};
#endif

View File

@ -0,0 +1,102 @@
//
// OVBenchmark.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVBenchmark_h
#define OVBenchmark_h
#include <ctime>
namespace OpenVanilla {
using namespace std;
class OVBenchmark
{
public:
OVBenchmark()
: m_used(false)
, m_running(false)
, m_start(0)
, m_elapsedTicks(0)
, m_elapsedSeconds(0.0)
{
}
void start()
{
m_used = true;
m_running = true;
m_elapsedSeconds = 0.0;
m_elapsedTicks = 0;
m_start = clock();
}
void stop()
{
if (m_running) {
update();
m_running = false;
}
}
clock_t elapsedTicks()
{
if (!m_used)
return 0;
if (m_running)
update();
return m_elapsedTicks;
}
double elapsedSeconds()
{
if (!m_used)
return 0;
if (m_running)
update();
return m_elapsedSeconds;
}
protected:
void update()
{
m_elapsedTicks = clock() - m_start;
m_elapsedSeconds = static_cast<double>(m_elapsedTicks) / CLOCKS_PER_SEC;
}
bool m_used;
bool m_running;
clock_t m_start;
clock_t m_elapsedTicks;
double m_elapsedSeconds;
};
};
#endif

View File

@ -0,0 +1,806 @@
//
// OVCINDataTable.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVCINDataTable_h
#define OVCINDataTable_h
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include "OVFileHelper.h"
#include "OVUTF8Helper.h"
#include "OVWildcard.h"
#include <map>
namespace OpenVanilla {
using namespace std;
// CIN := (COMMENT | PROPERTY | KEYNAME | CHARDEF)*
// EOL := \n|\r
// COMMENT := ^#.*(EOL)
// KEY := \w+
// VALUE := \w([\w\s]*\w)*
// PROPERTY: ^%(KEY)\s+(VALUE)(EOL)
// KEYNAME :=
// ^%keyname\s+begin(EOL)
// ^(KEY)\s+(VALUE)(EOL)
// ^%keyname\s+end(EOL)
// CHARDEF:
// ^%chardef\s+begin(EOL)
// ^(KEY)\s+(VALUE)(EOL)
// ^%chardef\s+end(EOL)
class OVCINDataTableParser;
class OVFastKeyValuePairMap {
public:
~OVFastKeyValuePairMap()
{
free(m_data);
}
size_t size()
{
return m_index;
}
pair<string, string> keyValuePairAtIndex(size_t index)
{
if (index >= m_index)
return pair<string, string>();
KVPair* entry = m_data + index;
return pair<string, string>(entry->key, entry->value);
}
vector<pair<string, string> > findPairsWithKey(const char* key)
{
return fetchValuesFromIndex(findFirstOccuranceOfKey(key), key);
}
vector<pair<string, string> > findPairsWithWildcard(const OVWildcard& pWildcard)
{
const OVWildcard* ptrWildcard = &pWildcard;
if (pWildcard.isCaseSensitive() != m_caseSensitive) {
OVWildcard newWildcard(pWildcard.expression(), pWildcard.matchOneChar(), pWildcard.matchZeroOrMoreChar(), m_caseSensitive);
ptrWildcard = &newWildcard;
}
const OVWildcard& wildcard = *ptrWildcard;
string headString = wildcard.longestHeadMatchString();
insensitivizeString(headString);
size_t hSLength = headString.length();
size_t start = findFirstOccuranceOfKey(headString.c_str(), true);
vector<pair<string, string> > result;
for (size_t index = start; index < m_index; index++) {
KVPair* entry = m_data + index;
string keyString = entry->key;
// if no more head matchZeroOrMoreChar
string keySubstr = keyString.substr(0, hSLength);
insensitivizeString(keySubstr);
if (keySubstr > headString)
break;
if (wildcard.match(keyString))
result.push_back(pair<string, string>(keyString, entry->value));
}
return result;
}
protected:
friend class OVCINDataTableParser;
OVFastKeyValuePairMap(size_t initSize, size_t growSize, bool caseSensitive = false)
: m_index(0)
, m_size(initSize ? initSize : 1)
, m_growSize(growSize)
, m_caseSensitive(caseSensitive)
{
m_data = (KVPair*)calloc(1, sizeof(KVPair) * m_size);
}
void add(char* key, char* value)
{
KVPair* entry = m_data + m_index;
entry->key = key;
entry->value = value;
m_index++;
if (m_index == m_size)
grow();
}
void sortAndFreeze()
{
m_size = m_index;
if (m_caseSensitive)
qsort(m_data, m_index, sizeof(KVPair), OVFastKeyValuePairMap::qsortCompareCaseSensitive);
else
qsort(m_data, m_index, sizeof(KVPair), OVFastKeyValuePairMap::qsortCompare);
}
void insensitivizeString(string& str)
{
if (m_caseSensitive)
return;
for (string::iterator iter = str.begin() ; iter != str.end() ; ++iter)
*iter = tolower(*iter);
}
protected:
vector<pair<string, string> > fetchValuesFromIndex(size_t start, const char* key)
{
vector<pair<string, string> > result;
for (size_t index = start ; index < m_index; index++) {
KVPair* entry = m_data + index;
if (compareString(entry->key, key) <= 0) {
result.push_back(pair<string, string>(entry->key, entry->value));
}
else {
break;
}
}
return result;
}
size_t findFirstOccuranceOfKey(const char* key, bool closest = false)
{
if (!m_index)
return m_index;
size_t mid, low = 0, high = m_index - 1;
while (low <= high) {
mid = (low + high) / 2;
char* entryKey = (m_data + mid)->key;
int cmp = compareString(key, entryKey);
if (!cmp) {
if (!mid)
return mid;
size_t oneUp = mid - 1;
if (!compareString(key, (m_data + oneUp)->key))
high = oneUp;
else
return mid;
}
else {
if (closest) {
if (mid > 0) {
if (compareString(key, (m_data + mid - 1)->key) > 0 && compareString(key, entryKey) <= 0)
return mid;
}
}
if (cmp < 0) {
if (!mid) {
if (closest)
return 0;
return m_index;
}
high = mid - 1;
}
else {
if (low + 1 >= m_index)
return m_index;
low = mid + 1;
}
}
}
return m_index;
}
int compareString(const char* a, const char* b)
{
#ifndef WIN32
return m_caseSensitive ? strcmp(a, b) : strcasecmp(a, b);
#else
return m_caseSensitive ? strcmp(a, b) : _stricmp(a, b);
#endif
}
static int qsortCompare(const void* a, const void* b)
{
int cmp;
char* aa = ((const KVPair*)a)->key;
char* bb = ((const KVPair*)b)->key;
#ifndef WIN32
if (!(cmp = strcasecmp(aa, bb)))
#else
if (!(cmp = _stricmp(aa, bb)))
#endif
return aa == bb ? 0 : (aa > bb ? 1 : -1);
else
return cmp;
}
static int qsortCompareCaseSensitive(const void* a, const void* b)
{
int cmp;
char* aa = ((const KVPair*)a)->key;
char* bb = ((const KVPair*)b)->key;
if (!(cmp = strcmp(aa, bb)))
return aa == bb ? 0 : (aa > bb ? 1 : -1);
else
return cmp;
}
void grow()
{
size_t growSize = m_growSize ? m_growSize : m_size;
KVPair* newData = (KVPair*)malloc(sizeof(KVPair) * (m_size + growSize));
memcpy(newData, m_data, sizeof(KVPair) * m_size);
memset(newData + m_size, 0, sizeof(KVPair) * growSize);
KVPair* tmp = m_data;
m_data = newData;
free(tmp);
m_size += growSize;
}
protected:
struct KVPair {
char* key;
char* value;
};
bool m_caseSensitive;
size_t m_growSize;
size_t m_size;
size_t m_index;
KVPair* m_data;
};
class OVCINDataTable {
public:
~OVCINDataTable()
{
if (m_propertyMap)
delete m_propertyMap;
if (m_keynameMap)
delete m_keynameMap;
if (m_chardefMap)
delete m_chardefMap;
if (m_data)
free (m_data);
}
string findProperty(const string& key)
{
vector<pair<string, string> > result = m_propertyMap->findPairsWithKey(key.c_str());
if (result.size()) return result[0].second;
return string();
}
string findKeyname(const string& key)
{
vector<pair<string, string> > result = m_keynameMap->findPairsWithKey(key.c_str());
if (result.size()) return result[0].second;
return string();
}
vector<string> findChardef(const string& key)
{
vector<pair<string, string> > ret = m_chardefMap->findPairsWithKey(key.c_str());
vector<string> result;
vector<pair<string, string> >::iterator iter= ret.begin();
for ( ; iter != ret.end(); iter++)
result.push_back((*iter).second);
return result;
}
vector<pair<string, string> > findChardefWithWildcard(const OVWildcard& wildcard)
{
return m_chardefMap->findPairsWithWildcard(wildcard);
}
OVFastKeyValuePairMap* propertyMap()
{
return m_propertyMap;
}
OVFastKeyValuePairMap* keynameMap()
{
return m_keynameMap;
}
OVFastKeyValuePairMap* chardefMap()
{
return m_chardefMap;
}
protected:
friend class OVCINDataTableParser;
OVCINDataTable(char* data, OVFastKeyValuePairMap* propertyMap, OVFastKeyValuePairMap* keynameMap, OVFastKeyValuePairMap* chardefMap)
: m_data(data)
, m_propertyMap(propertyMap)
, m_keynameMap(keynameMap)
, m_chardefMap(chardefMap)
{
}
char* m_data;
OVFastKeyValuePairMap* m_propertyMap;
OVFastKeyValuePairMap* m_keynameMap;
OVFastKeyValuePairMap* m_chardefMap;
};
class OVCINDataTableParser {
public:
enum {
NoFileError,
SeekError,
EmptyFileError,
MemoryAllocationError,
ReadError,
NoDataError = EmptyFileError
};
OVCINDataTableParser()
: m_data(0)
, m_lastError(0)
{
}
~OVCINDataTableParser()
{
if (m_data)
free(m_data);
}
int lastError()
{
return m_lastError;
}
OVCINDataTable* CINDataTableFromFileName(const string& filename, bool caseSensitive = false)
{
if (m_data) {
free(m_data);
m_data = 0;
}
FILE* f = OVFileHelper::OpenStream(filename);
if (!f) {
m_lastError = NoFileError;
return 0;
}
OVCINDataTable* table;
OVCINDataTableParser parser;
table = parser.CINDataTableFromFileStream(f, caseSensitive);
fclose(f);
return table;
}
OVCINDataTable* CINDataTableFromString(const char* string, bool caseSensitive = false)
{
if (m_data) {
free(m_data);
m_data = 0;
}
size_t len = strlen(string);
if (!len) {
m_lastError = NoDataError;
return 0;
}
m_data = (char*)calloc(1, len + 1);
if (!m_data) {
m_lastError = MemoryAllocationError;
return 0;
}
memcpy(m_data, string, len);
return CINDataTableFromRetainedData(caseSensitive);
}
OVCINDataTable* CINDataTableFromFileStream(FILE* stream, bool caseSensitive = false)
{
if (m_data) {
free(m_data);
m_data = 0;
}
if (!stream) {
m_lastError = NoFileError;
return 0;
}
if (fseek(stream, 0, SEEK_END) == -1) {
m_lastError = SeekError;
return 0;
}
size_t size;
if (!(size = ftell(stream))) {
m_lastError = EmptyFileError;
return 0;
}
if (fseek(stream, 0, SEEK_SET) == -1) {
m_lastError = SeekError;
return 0;
}
m_data = (char*)calloc(1, size + 1);
if (!m_data) {
m_lastError = MemoryAllocationError;
return 0;
}
if (fread(m_data, 1, size, stream) != size) {
m_lastError = ReadError;
return 0;
}
return CINDataTableFromRetainedData(caseSensitive);
}
protected:
OVCINDataTable* CINDataTableFromRetainedData(bool caseSensitive)
{
OVFastKeyValuePairMap* propertyMap = new OVFastKeyValuePairMap(16, 0, caseSensitive);
if (!propertyMap) {
free(m_data);
m_lastError = MemoryAllocationError;
return 0;
}
OVFastKeyValuePairMap* keynameMap = new OVFastKeyValuePairMap(64, 0, caseSensitive);
if (!keynameMap) {
free(m_data);
delete propertyMap;
m_lastError = MemoryAllocationError;
return 0;
}
OVFastKeyValuePairMap* chardefMap = new OVFastKeyValuePairMap(1024, 0, caseSensitive);
if (!chardefMap) {
free(m_data);
delete propertyMap;
delete keynameMap;
m_lastError = MemoryAllocationError;
return 0;
}
m_scanner = m_data;
char first;
int blockMode = 0;
while (first = *m_scanner) {
if (blockMode) {
if (first == '\r' || first == '\n') {
m_scanner++;
continue;
}
char* key = m_scanner;
char* value = const_cast<char*>("");
char endingChar = skipToSpaceCharOrLineEndAndMarkAndForward();
if (endingChar == '\r' || endingChar == '\n') {
;
}
else {
endingChar = skipUntilNonSpaceChar();
if (endingChar == '\r' || endingChar == '\n') {
;
}
else {
value = m_scanner;
skipToLineEndAndMarkAndForwardWithoutTrailingSpace();
}
}
if (blockMode == 1) {
if (!strcmp(key, "%keyname") && !strcmp(value, "end")) {
blockMode = 0;
}
else {
if (!caseSensitive)
makeLowerCase(key);
keynameMap->add(key, value);
}
}
else if (blockMode == 2) {
if (!strcmp(key, "%chardef") && !strcmp(value, "end")) {
blockMode = 0;
}
else {
if (!caseSensitive)
makeLowerCase(key);
chardefMap->add(key, value);
}
}
continue;
}
if (first == '#') {
skipUntilNextLine();
continue;
}
if (first == '%') {
m_scanner++;
char* key;
char* value = const_cast<char*>("");
if (*(key = m_scanner)) {
char endingChar = skipToSpaceCharOrLineEndAndMarkAndForward();
if (endingChar == '\r' || endingChar == '\n') {
;
}
else {
endingChar = skipUntilNonSpaceChar();
if (endingChar == '\r' || endingChar == '\n') {
;
}
else {
value = m_scanner;
skipToLineEndAndMarkAndForwardWithoutTrailingSpace();
}
}
if (!strcmp(key, "keyname") && !strcmp(value, "begin")) {
blockMode = 1;
}
else if (!strcmp(key, "chardef") && !strcmp(value, "begin")) {
blockMode = 2;
}
else {
propertyMap->add(key, value);
}
}
continue;
}
m_scanner++;
}
propertyMap->sortAndFreeze();
keynameMap->sortAndFreeze();
chardefMap->sortAndFreeze();
OVCINDataTable* table = new OVCINDataTable(m_data, propertyMap, keynameMap, chardefMap);
if (!table) {
free(m_data);
delete propertyMap;
delete keynameMap;
delete chardefMap;
m_lastError = MemoryAllocationError;
return 0;
}
else {
m_data = 0;
}
return table;
}
void skipUntilNextLine()
{
skipUntilEitherCRLF();
skipUntilNeitherCRLF();
}
void skipUntilEitherCRLF()
{
char nextChar;
while (nextChar = *m_scanner) {
if (nextChar == '\r' || nextChar == '\n') break;
m_scanner++;
}
}
void skipUntilNeitherCRLF()
{
char nextChar;
while (nextChar = *m_scanner) {
if (!(nextChar == '\r' || nextChar == '\n')) break;
m_scanner++;
}
}
void skipToLineEndAndMarkAndForwardWithoutTrailingSpace()
{
char nextChar;
while (nextChar = *m_scanner) {
if (nextChar == ' ' || nextChar == '\t') {
char* begin = m_scanner;
m_scanner++;
while (nextChar = *m_scanner) {
if (!(nextChar == ' ' || nextChar == '\t')) break;
m_scanner++;
}
if (nextChar == '\n' || nextChar == '\r') {
*begin = 0;
m_scanner++;
return;
}
else {
m_scanner++;
continue;
}
}
if (nextChar == '\n' || nextChar == '\r') {
*m_scanner = 0;
m_scanner++;
return;
}
m_scanner++;
}
}
char skipToSpaceCharOrLineEndAndMarkAndForward()
{
char nextChar;
while (nextChar = *m_scanner) {
if (nextChar == ' ' || nextChar == '\t' || nextChar == '\n' || nextChar == '\r') {
*m_scanner = 0;
m_scanner++;
return nextChar;
}
m_scanner++;
}
return 0;
}
char skipUntilNonSpaceChar()
{
char nextChar;
while (nextChar = *m_scanner) {
if (!(nextChar == ' ' || nextChar == '\t'))
return nextChar;
m_scanner++;
}
return 0;
}
void makeLowerCase(char* ptr)
{
while (*ptr) {
*ptr = tolower(*ptr);
ptr++;
}
}
protected:
char* m_data;
char* m_scanner;
int m_lastError;
public:
static const map<string, string> QuickParseProperty(const string& filename)
{
map<string, string> properties;
FILE* stream = OVFileHelper::OpenStream(filename);
if (!stream)
return properties;
while (!feof(stream)) {
char buffer[256];
fgets(buffer, sizeof(buffer) - 1, stream);
if (!*buffer)
continue;
if (*buffer == '#')
continue;
pair<string, string> pv = SplitPropertyString(buffer + 1);
if (pv.first == "keyname")
break;
properties[pv.first] = pv.second;
}
fclose(stream);
return properties;
}
static pair<string, string> SplitPropertyString(const char* str)
{
const char* scanner = str;
while (*scanner) {
if (*scanner == ' ' || *scanner == '\t' || *scanner == '\r' || *scanner == '\n')
break;
scanner++;
}
string property = string(str, (size_t)(scanner - str));
while (*scanner) {
if (*scanner != ' ' && *scanner != '\t')
break;
scanner++;
}
const char* begin = scanner;
while (*scanner) {
if (*scanner == '\r' || *scanner == '\n')
break;
scanner++;
}
string value = string(begin, (size_t)(scanner - begin));
return pair<string, string>(property, value);
}
};
};
#endif

View File

@ -0,0 +1,189 @@
//
// OVCINDatabaseService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVCINDatabaseService_h
#define OVCINDatabaseService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVCINDataTable.h>
#include <OpenVanilla/OVDatabaseService.h>
#else
#include "OVCINDataTable.h"
#include "OVDatabaseService.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVCINDatabaseService;
class OVCINKeyValueDataTable : public OVKeyValueDataTableInterface
{
public:
~OVCINKeyValueDataTable()
{
delete m_table;
}
virtual const vector<string> valuesForKey(const string& key)
{
return m_table->findChardef(key);
}
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression)
{
return m_table->findChardefWithWildcard(expression);
}
virtual const string valueForProperty(const string& property)
{
if (OVKeynamePropertyHelper::IsPropertyKeyname(property))
return m_table->findKeyname(OVKeynamePropertyHelper::KeynameFromProperty(property));
else
return m_table->findProperty(property);
}
protected:
OVCINDataTable* m_table;
friend class OVCINDatabaseService;
OVCINKeyValueDataTable(OVCINDataTable* table)
: m_table(table)
{
}
};
class OVCINDatabaseService : public OVDatabaseService {
public:
OVCINDatabaseService()
{
}
OVCINDatabaseService(const string& pathToScan, const string& includePattern = "*.cin", const string& excludePattern = "", size_t depth = 1)
{
addDirectory(pathToScan, includePattern, excludePattern, depth);
}
// note addDirectory overwrites the table data, so scan user directory after scan the systems if you want to give precedence to user' tables
void addDirectory(const string& pathToScan, const string& includePattern = "*.cin", const string& excludePattern = "", size_t depth = 1)
{
string pathPrefix = OVPathHelper::NormalizeByExpandingTilde(pathToScan) + OVPathHelper::Separator();
size_t prefixLength = pathPrefix.length();
vector<string> tables = OVDirectoryHelper::Glob(pathPrefix, includePattern, excludePattern, depth);
vector<string>::iterator iter = tables.begin();
for ( ; iter != tables.end(); ++iter) {
const string& path = *iter;
string shortPath = *iter;
shortPath.erase(0, prefixLength);
string tableName = OVCINDatabaseService::TableNameFromPath(shortPath);
m_tables[tableName] = path;
}
}
virtual const vector<string> tables(const OVWildcard& filter = string("*"))
{
vector<string> result;
for (map<string, string>::iterator iter = m_tables.begin() ; iter != m_tables.end(); ++iter) {
if (filter.match((*iter).first))
result.push_back((*iter).first);
}
return result;
}
virtual bool tableSupportsValueToKeyLookup(const string &tableName)
{
return false;
}
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false)
{
map<string, string>::iterator iter = m_tables.find(name);
if (iter == m_tables.end())
return 0;
OVCINDataTableParser parser;
OVCINDataTable* table = parser.CINDataTableFromFileName((*iter).second, suggestedCaseSensitivity);
if (!table)
return 0;
return new OVCINKeyValueDataTable(table);
}
virtual const string valueForPropertyInTable(const string& property, const string& name)
{
map<string, string>::iterator iter;
if (name != m_cachedTableName)
{
iter = m_tables.find(name);
if (iter == m_tables.end())
return string();
m_cachedProperties = OVCINDataTableParser::QuickParseProperty((*iter).second);
m_cachedTableName = name;
}
iter = m_cachedProperties.find(property);
if (iter != m_cachedProperties.end())
return (*iter).second;
return string();
}
protected:
map<string, string> m_tables;
map<string, string> m_cachedProperties;
string m_cachedTableName;
public:
static const string TableNameFromPath(const string& path)
{
string result;
char separator = OVPathHelper::Separator();
string::const_iterator iter = path.begin();
for ( ; iter != path.end(); ++iter)
if (*iter == separator || *iter == '.')
result += '-';
else
result += *iter;
return result;
}
};
};
#endif

View File

@ -0,0 +1,125 @@
//
// OVCINToSQLiteConvertor.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVCINToSQLiteConvertor_h
#define OVCINToSQLiteConvertor_h
#if defined(__APPLE__)
#include <OpenVanilla/OVCINDataTable.h>
#include <OpenVanilla/OVSQLiteWrapper.h>
#else
#include "OVCINDataTable.h"
#include "OVSQLiteWrapper.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVCINToSQLiteConvertor {
protected:
static bool InsertKeyValue(OVFastKeyValuePairMap* map, OVSQLiteStatement* statement, const char* prefix = 0)
{
string prefixString = prefix ? prefix : "";
size_t size = map->size();
for (size_t index = 0; index < size; index++) {
pair<string, string> kvpair = map->keyValuePairAtIndex(index);
const string& key = prefix ? prefixString + kvpair.first : kvpair.first;
statement->bindTextToColumn(key, 1);
statement->bindTextToColumn(kvpair.second, 2);
if (statement->step() != SQLITE_DONE)
return false;
statement->reset();
}
return true;
}
public:
static bool Convert(OVCINDataTable* table, OVSQLiteConnection* connection, const string& tableName, bool overwriteTable = true)
{
const char* nameStr = tableName.c_str();
// query if the table exists
OVSQLiteStatement* statement;
statement = connection->prepare("SELECT name FROM sqlite_master WHERE name = %Q", nameStr);
if (!statement)
return false;
if (statement->step() == SQLITE_ROW && overwriteTable)
{
delete statement;
if (connection->execute("DROP TABLE %Q", nameStr) != SQLITE_OK) {
delete statement;
return false;
}
}
else
delete statement;
if (connection->execute("CREATE TABLE %Q (key, value)", nameStr) != SQLITE_OK)
return false;
string indexName = tableName + "_index";
if (connection->execute("CREATE INDEX %Q on %Q (key)", indexName.c_str(), nameStr) != SQLITE_OK)
return false;
statement = connection->prepare("INSERT INTO %Q VALUES (?, ?)", nameStr);
if (!statement) {
return false;
}
if (connection->execute("BEGIN") != SQLITE_OK) {
return false;
}
string keynameProperty = string(OVPropertyStringInternalPrefix) + string(OVCINKeynameString);
if (InsertKeyValue(table->propertyMap(), statement, OVPropertyStringInternalPrefix))
if (InsertKeyValue(table->keynameMap(), statement, keynameProperty.c_str()))
InsertKeyValue(table->chardefMap(), statement);
delete statement;
if (connection->execute("COMMIT") != SQLITE_OK) {
return false;
}
return true;
}
};
};
#endif

View File

@ -0,0 +1,208 @@
//
// OVCandidateService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVCandidateService_h
#define OVCandidateService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#include <OpenVanilla/OVKey.h>
#include <OpenVanilla/OVLoaderService.h>
#else
#include "OVBase.h"
#include "OVKey.h"
#include "OVLoaderService.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVCandidateList : public OVBase {
public:
virtual void clear() = 0;
virtual size_t size() const = 0;
virtual string candidateAtIndex(size_t index) const = 0;
virtual void setCandidate(size_t index, const string& candidate) = 0;
virtual void setCandidates(const vector<string>& candidates) = 0;
virtual void addCandidate(const string& candidate) = 0;
virtual void addCandidates(const vector<string>& candidates) = 0;
};
class OVCandidatePanel;
class OVOneDimensionalCandidatePanel;
// class OVTwoDimensionalCandidatePanel;
class OVFreeContentPanel;
class OVPlainTextCandidatePanel;
class OVHTMLCandidatePanel;
class OVCandidatePanel : public OVBase {
public:
virtual bool isOneDimensionalPanel() const
{
return false;
}
virtual bool isTwoDimensionalPanel() const
{
return false;
}
virtual bool isPlainTextPanelPanel() const
{
return false;
}
virtual bool isHTMLPanel() const
{
return false;
}
virtual void hide() = 0;
virtual void show() = 0;
virtual void updateDisplay() = 0;
virtual bool isVisible() = 0;
virtual void setPrompt(const string& prompt) = 0;
virtual string prompt() = 0;
virtual bool yieldToCandidateEventHandler() = 0;
virtual void cancelEventHandler() = 0;
virtual void reset() = 0;
};
class OVOneDimensionalCandidatePanel : public OVCandidatePanel {
public:
virtual bool isOneDimensionalPanel() const
{
return true;
}
virtual bool isHorizontal() const = 0;
virtual bool isVertical() const = 0;
virtual OVCandidateList* candidateList() = 0;
virtual size_t candidatesPerPage() const = 0;
virtual void setCandidatesPerPage(size_t number) = 0;
virtual size_t pageCount() const = 0;
virtual size_t currentPage() const = 0;
virtual size_t currentPageCandidateCount() const = 0;
virtual bool allowsPageWrapping() const = 0;
virtual void setAllowsPageWrapping(bool allowsPageWrapping) = 0;
virtual size_t currentHightlightIndex() const = 0;
virtual void setHighlightIndex(size_t index) = 0;
virtual size_t currentHightlightIndexInCandidateList() const = 0;
virtual size_t goToNextPage() = 0;
virtual size_t goToPreviousPage() = 0;
virtual size_t goToPage(size_t page) = 0;
virtual const OVKey candidateKeyAtIndex(size_t index) = 0;
virtual void setCandidateKeys(const string& asciiKeys, OVLoaderService* loaderService)
{
OVKeyVector keys;
for (size_t index = 0; index < asciiKeys.length(); index++) {
keys.push_back(loaderService->makeOVKey(asciiKeys[index]));
}
setCandidateKeys(keys);
setCandidatesPerPage(asciiKeys.length());
}
virtual void setCandidateKeys(const OVKeyVector& keys) = 0;
virtual void setNextPageKeys(const OVKeyVector& keys) = 0;
virtual void setPreviousPageKeys(const OVKeyVector& keys) = 0;
virtual void setNextCandidateKeys(const OVKeyVector& keys) = 0;
virtual void setPreviousCandidateKeys(const OVKeyVector& keys) = 0;
virtual void setCancelKeys(const OVKeyVector& keys) = 0;
virtual void setChooseHighlightedCandidateKeys(const OVKeyVector& keys) = 0;
virtual const OVKeyVector defaultCandidateKeys() const = 0;
virtual const OVKeyVector defaultNextPageKeys() const = 0;
virtual const OVKeyVector defaultNextCandidateKeys() const = 0;
virtual const OVKeyVector defaultPreviousPageKeys() const = 0;
virtual const OVKeyVector defaultPreviousCandidateKeys() const = 0;
virtual const OVKeyVector defaultCancelKeys() const = 0;
virtual const OVKeyVector defaultChooseHighlightedCandidateKeys() const = 0;
};
class OVFreeContentStorage : public OVBase {
public:
virtual void clear() = 0;
virtual void setContent(const string& content) = 0;
virtual void appendContent(const string& content) = 0;
};
class OVPlainTextCandidatePanel : public OVCandidatePanel {
public:
virtual bool isPlainTextPanelPanel()
{
return true;
}
virtual OVFreeContentStorage* textStorage() = 0;
};
class OVHTMLCandidatePanel : public OVCandidatePanel {
public:
virtual OVFreeContentStorage* HTMLSourceStorage() = 0;
};
class OVCandidateService : public OVBase {
public:
virtual OVOneDimensionalCandidatePanel* useHorizontalCandidatePanel()
{
return 0;
}
virtual OVOneDimensionalCandidatePanel* useVerticalCandidatePanel()
{
return 0;
}
virtual OVOneDimensionalCandidatePanel* useOneDimensionalCandidatePanel()
{
return useVerticalCandidatePanel();
}
// virtual OVTwoDimensionalCandidatePanel* twoDimensionalCandidatePanel();
virtual OVPlainTextCandidatePanel* usePlainTextCandidatePanel()
{
return 0;
}
virtual OVHTMLCandidatePanel* useHTMLCandidatePanel()
{
return 0;
}
};
};
#endif

View File

@ -0,0 +1,101 @@
//
// OVDatabaseService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVDatabaseService_h
#define OVDatabaseService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#include <OpenVanilla/OVCINDataTable.h>
#include <OpenVanilla/OVFileHelper.h>
#include <OpenVanilla/OVWildcard.h>
#else
#include "OVBase.h"
#include "OVCINDataTable.h"
#include "OVFileHelper.h"
#include "OVWildcard.h"
#endif
#include <map>
namespace OpenVanilla {
using namespace std;
// database-backed table uses this prefix to store properties ina key-value data table
#define OVPropertyStringInternalPrefix "__property_"
#define OVCINKeynameString "keyname-"
#define OVCINKeynameStringLength 8
// keyname is defined in the .cin format, not to be confused with the key in key-value pairs
class OVKeynamePropertyHelper : public OVBase {
public:
static bool IsPropertyKeyname(const string& property)
{
return (property.substr(0, OVCINKeynameStringLength) == OVCINKeynameString);
}
// passes property and gets back the keyname
static const string KeynameFromProperty(const string& property)
{
return IsPropertyKeyname(property) ? property.substr(OVCINKeynameStringLength, property.length() - OVCINKeynameStringLength) : string();
}
// passes keyname and gets the combined property
static const string KeynameToProperty(const string& keyname)
{
return string(OVCINKeynameString) + keyname;
}
};
class OVKeyValueDataTableInterface : public OVBase {
public:
virtual const vector<string> valuesForKey(const string& key) = 0;
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression) = 0;
virtual const string valueForProperty(const string& property) = 0;
// only supported by database services that support value-to-key lookup, the default implementation is an empty vector<string>
virtual const vector<string> keysForValue(const string& value)
{
return vector<string>();
}
};
class OVDatabaseService : public OVBase {
public:
virtual const vector<string> tables(const OVWildcard& filter = string("*")) = 0;
virtual bool tableSupportsValueToKeyLookup(const string &tableName) = 0;
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false) = 0;
// this is needed so that modules like OVIMGeneric can know table localized names in advance, without really loading them
virtual const string valueForPropertyInTable(const string& property, const string& name) = 0;
};
};
#endif

View File

@ -0,0 +1,149 @@
//
// OVDateTimeHelper.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVDateTimeHelper_h
#define OVDateTimeHelper_h
#include <ctime>
#include <sstream>
#include <string>
namespace OpenVanilla {
using namespace std;
class OVDateTimeHelper
{
public:
static time_t GetTimeIntervalSince1970()
{
return time(NULL);
}
static time_t GetTimeIntervalSince1970FromString(const string& s)
{
stringstream sst;
sst << s;
time_t t;
sst >> t;
return t;
}
static const string GetTimeIntervalSince1970AsString()
{
stringstream sst;
sst << time(NULL);
return sst.str();
}
static time_t GetTimeIntervalSince1970AtBeginningOfTodayLocalTime()
{
time_t t = time(NULL);
#ifdef WIN32
struct tm tdata;
struct tm* td = &tdata;
if (localtime_s(td, &t))
return 0;
#else
struct tm* td;
td = localtime(&t);
#endif
td->tm_hour = 0;
td->tm_min = 0;
td->tm_sec = 0;
return mktime(td);
}
static const string LocalTimeString()
{
time_t t = time(NULL);
#ifdef WIN32
struct tm tdata;
struct tm* td = &tdata;
if (localtime_s(td, &t))
return string();
#else
struct tm* td;
td = localtime(&t);
#endif
ostringstream sstr;
sstr.width(2);
sstr.fill('0');
sstr << td->tm_hour << ":";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_min << ":";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_sec;
return sstr.str();
}
static const string LocalDateTimeString()
{
time_t t = time(NULL);
#ifdef WIN32
struct tm tdata;
struct tm* td = &tdata;
if (localtime_s(td, &t))
return string();
#else
struct tm* td;
td = localtime(&t);
#endif
ostringstream sstr;
sstr.width(4);
sstr << td->tm_year + 1900 << "-";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_mon + 1 << "-";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_mday << " ";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_hour << ":";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_min << ":";
sstr.width(2);
sstr.fill('0');
sstr << td->tm_sec;
return sstr.str();
}
};
};
#endif

View File

@ -0,0 +1,72 @@
//
// OVEncodingService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVEncodingService_h
#define OVEncodingService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVUTF8Helper.h>
#else
#include "OVUTF8Helper.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVEncodingService : public OVBase {
public:
virtual bool stringSupportedByEncoding(const string& text, const string& encoding)
{
vector<string> svec = OVUTF8Helper::SplitStringByCodePoint(text);
for (vector<string>::iterator iter = svec.begin() ; iter != svec.end() ; ++iter)
if (!codepointSupportedByEncoding(*iter, encoding))
return false;
return true;
}
virtual bool stringSupportedBySystem(const string& text)
{
vector<string> svec = OVUTF8Helper::SplitStringByCodePoint(text);
for (vector<string>::iterator iter = svec.begin() ; iter != svec.end() ; ++iter)
if (!codepointSupportedBySystem(*iter))
return false;
return true;
}
virtual bool codepointSupportedByEncoding(const string& codepoint, const string& encoding) = 0;
virtual bool codepointSupportedBySystem(const string& codepoint) = 0;
virtual const vector<string> supportedEncodings() = 0;
virtual bool isEncodingSupported(const string& encoding) = 0;
virtual bool isEncodingConversionSupported(const string& fromEncoding, const string& toEncoding) = 0;
virtual const pair<bool, string> convertEncoding(const string& fromEncoding, const string& toEncoding, const string& text) = 0;
};
};
#endif

View File

@ -0,0 +1,102 @@
//
// OVEventHandlingContext.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVEventHandlingContext_h
#define OVEventHandlingContext_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#include <OpenVanilla/OVCandidateService.h>
#include <OpenVanilla/OVStringHelper.h>
#include <OpenVanilla/OVTextBuffer.h>
#include <OpenVanilla/OVKey.h>
#include <OpenVanilla/OVLoaderService.h>
#else
#include "OVBase.h"
#include "OVCandidateService.h"
#include "OVStringHelper.h"
#include "OVTextBuffer.h"
#include "OVKey.h"
#include "OVLoaderService.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVEventHandlingContext : public OVBase {
public:
virtual void startSession(OVLoaderService* loaderService)
{
}
virtual void stopSession(OVLoaderService* loaderService)
{
}
virtual void clear(OVLoaderService* loaderService)
{
stopSession(loaderService);
startSession(loaderService);
}
virtual bool handleKey(OVKey* key, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
{
return false;
}
virtual bool handleDirectText(const vector<string>& segments, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
{
return handleDirectText(OVStringHelper::Join(segments), readingText, composingText, candidateService, loaderService);
}
virtual bool handleDirectText(const string&, OVTextBuffer* readingText, OVTextBuffer* composingText, OVCandidateService* candidateService, OVLoaderService* loaderService)
{
return false;
}
virtual void candidateCanceled(OVCandidateService* candidateService, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
{
}
virtual bool candidateSelected(OVCandidateService* candidateService, const string& text, size_t index, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
{
return true;
}
virtual bool candidateNonPanelKeyReceived(OVCandidateService* candidateService, const OVKey* key, OVTextBuffer* readingText, OVTextBuffer* composingText, OVLoaderService* loaderService)
{
return false;
}
virtual const string filterText(const string& inputText, OVLoaderService* loaderService)
{
return inputText;
}
};
};
#endif

View File

@ -0,0 +1,46 @@
//
// OVException.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVException_h
#define OVException_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#else
#include "OVBase.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVException {
public:
class OverflowException {};
};
};
#endif

View File

@ -0,0 +1,627 @@
//
// OVFileHelper.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVFileHelper_h
#define OVFileHelper_h
#if defined(__APPLE__)
#include <dirent.h>
#include <stdio.h>
#else
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
#endif
#include <sys/stat.h>
#include <fstream>
#include <algorithm>
#include <vector>
#include "OVWildcard.h"
#include "OVUTF8Helper.h"
namespace OpenVanilla {
using namespace std;
class OVFileHelper {
public:
static FILE* OpenStream(const string& filename, const string& mode = "rb")
{
#ifndef WIN32
return fopen(filename.c_str(), mode.c_str());
#else
FILE* stream = NULL;
errno_t err = _wfopen_s(&stream, OVUTF16::FromUTF8(filename).c_str(), OVUTF16::FromUTF8(mode).c_str());
return err ? 0 : stream;
#endif
}
static void OpenOFStream(ofstream& stream, const string& filename, ios_base::openmode openMode)
{
#ifndef WIN32
stream.open(filename.c_str(), openMode);
#else
stream.open(OVUTF16::FromUTF8(filename).c_str(), openMode);
#endif
}
static void OpenIFStream(ifstream& stream, const string& filename, ios_base::openmode openMode)
{
#ifndef WIN32
stream.open(filename.c_str(), openMode);
#else
stream.open(OVUTF16::FromUTF8(filename).c_str(), openMode);
#endif
}
// use free(), not delete[], to free the block allocated
static pair<char*, size_t> SlurpFile(const string& filename, bool addOneByteOfStringTerminationPadding = false)
{
FILE* stream = OpenStream(filename);
char* buf = 0;
size_t size = 0;
if (stream) {
if (!fseek(stream, 0, SEEK_END)) {
long lsize = ftell(stream);
if (lsize) {
size = (size_t)lsize;
if (!fseek(stream, 0, SEEK_SET)) {
buf = (char*)calloc(1, (size_t)size + (addOneByteOfStringTerminationPadding ? 1 : 0));
if (buf) {
if (fread(buf, size, 1, stream) != 1) {
free(buf);
buf = 0;
size = 0;
}
}
else {
size = 0;
}
}
else {
size = 0;
}
}
}
fclose(stream);
}
return pair<char*, size_t>(buf, size);
}
};
class OVFileTimestamp {
public:
#if defined(__APPLE__)
OVFileTimestamp(__darwin_time_t timestamp = 0, long subtimestamp = 0)
#elif defined(WIN32)
OVFileTimestamp(time_t timestamp = 0, time_t subtimestamp = 0)
#else
#error We don't know about Linux yet, sorry.
#endif
: m_timestamp(timestamp)
, m_subtimestamp(subtimestamp)
{
}
OVFileTimestamp(const OVFileTimestamp& timestamp)
: m_timestamp(timestamp.m_timestamp)
, m_subtimestamp(timestamp.m_subtimestamp)
{
}
OVFileTimestamp& operator=(const OVFileTimestamp& timestamp)
{
m_timestamp = timestamp.m_timestamp;
m_subtimestamp = timestamp.m_subtimestamp;
return *this;
}
bool operator==(OVFileTimestamp& another)
{
return (m_timestamp == another.m_timestamp) && (m_subtimestamp == another.m_subtimestamp);
}
bool operator!=(OVFileTimestamp& another)
{
return (m_timestamp != another.m_timestamp) || (m_subtimestamp != another.m_subtimestamp);
}
bool operator<(OVFileTimestamp& another)
{
return (m_timestamp < another.m_timestamp) || ((m_timestamp == another.m_timestamp) && m_subtimestamp < another.m_subtimestamp);
}
bool operator>(OVFileTimestamp& another)
{
return (m_timestamp > another.m_timestamp) || ((m_timestamp == another.m_timestamp) && m_subtimestamp > another.m_subtimestamp);
}
protected:
#if defined(__APPLE__)
__darwin_time_t m_timestamp;
long m_subtimestamp;
#elif defined(WIN32)
time_t m_timestamp;
time_t m_subtimestamp;
#else
#error We don't know about Linux yet, sorry.
#endif
};
class OVPathHelper {
public:
static char Separator()
{
#ifndef WIN32
return '/';
#else
return '\\';
#endif
}
static const string DirectoryFromPath(const string& path)
{
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
if (OVPathHelper::PathExists(realPath) && OVPathHelper::IsDirectory(realPath))
return realPath;
char separator = OVPathHelper::Separator();
if (!realPath.length())
return string(".");
for (size_t index = realPath.length() - 1; index >= 0 ; index--) {
if (realPath[index] == separator) {
if (index) {
// reserve the \\ on Windows
if (realPath[index-1] == '\\')
return realPath.substr(0, index + 1);
else
return realPath.substr(0, index);
}
else
return realPath.substr(0, 1);
}
// if we run into : (like C:) on Windows
if (realPath[index] == ':')
return realPath.substr(0, index + 1) + Separator();
if (!index) break;
}
return string(".");
}
static const string FilenameWithoutPath(const string &path)
{
char separator = OVPathHelper::Separator();
if (!path.length())
return string();
for (size_t index = path.length() - 1; index >= 0 ; index--) {
if (path[index] == separator)
return path.substr(index + 1, path.length() - (index + 1));
if (!index) break;
}
return path;
}
static const string FilenameWithoutExtension(const string &path)
{
char separator = OVPathHelper::Separator();
if (!path.length())
return string();
for (size_t index = path.length() - 1; index >= 0 ; index--) {
if (path[index] == separator)
break;
if (path[index] == '.')
return path.substr(0, index);
if (!index) break;
}
return path;
}
static const string ChopTrailingSeparator(const string& path)
{
if (path.length() == 1 && path[0] == Separator())
return path;
string result;
if (path.length()) {
if (path[path.length() - 1] == Separator())
result = path.substr(0, path.length() - 1);
else
result = path;
}
return result;
}
static const string ChopLeadingSeparator(const string& path)
{
if (path.length() == 1 && path[0] == Separator())
return path;
string result;
if (path.length()) {
if (path[0] == Separator()) {
result = path.substr(1, path.length() - 1);
}
else {
result = path;
}
}
return result;
}
static const string PathCat(const string& s1, const string& s2)
{
if (s2.length())
return ChopTrailingSeparator(s1) + Separator() + ChopLeadingSeparator(s2);
else
return s1;
}
static const string Normalize(const string& path)
{
string newPath;
size_t length = path.length();
for (size_t index = 0; index < length; index++) {
if (path[index] == '/' || path[index] == '\\') {
if (index < length - 1) {
if (path[index+1] == '/' || path[index+1] == '\\')
index++;
}
newPath += Separator();
}
else
newPath += path[index];
}
return ChopTrailingSeparator(newPath);
}
static const bool PathExists(const string& path)
{
#ifndef WIN32
struct stat buf;
return !stat(path.c_str(), &buf);
#else
struct _stat buf;
wstring wpath = OVUTF16::FromUTF8(path);
return !_wstat(wpath.c_str(), &buf);
#endif
}
static const bool IsDirectory(const string& path)
{
#ifndef WIN32
struct stat buf;
if (!stat(path.c_str(), &buf))
{
if (buf.st_mode & S_IFDIR)
return true;
}
#else
struct _stat buf;
wstring wpath = OVUTF16::FromUTF8(path);
if (!_wstat(wpath.c_str(), &buf))
{
if (buf.st_mode & S_IFDIR)
return true;
}
#endif
return false;
}
static const OVFileTimestamp TimestampForPath(const string& path)
{
OVFileTimestamp timestamp;
#if defined(__APPLE__)
struct stat buf;
if (!stat(path.c_str(), &buf))
{
timestamp = OVFileTimestamp(buf.st_mtimespec.tv_sec, buf.st_mtimespec.tv_nsec);
}
#elif defined(WIN32)
struct _stat buf;
wstring wpath = OVUTF16::FromUTF8(path);
if (!_wstat(wpath.c_str(), &buf))
{
timestamp = OVFileTimestamp(buf.st_mtime);
}
#else
#error Sorry, no idea for Linux yet.
#endif
return timestamp;
}
static bool RemoveEverythingAtPath(const string& path);
static const string NormalizeByExpandingTilde(const string& path);
};
class OVDirectoryHelper {
public:
static bool MakeDirectory(const string& path)
{
#ifndef WIN32
return !mkdir(path.c_str(), S_IRWXU);
#else
wstring wpath = OVUTF16::FromUTF8(path);
return CreateDirectoryW(wpath.c_str(), NULL) == TRUE;
#endif
}
static bool MakeDirectoryWithImmediates(const string& path)
{
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
if (OVPathHelper::PathExists(realPath) && OVPathHelper::IsDirectory(realPath)) {
return true;
}
string lastPart = OVPathHelper::DirectoryFromPath(realPath);
if (lastPart != realPath && !OVPathHelper::PathExists(lastPart)) {
if (!MakeDirectoryWithImmediates(lastPart))
return false;
}
return MakeDirectory(realPath);
}
static bool CheckDirectory(const string& path)
{
string realPath = OVPathHelper::NormalizeByExpandingTilde(path);
if (OVPathHelper::PathExists(realPath))
return OVPathHelper::IsDirectory(realPath);
return MakeDirectoryWithImmediates(realPath);
}
static const vector<string> Glob(const string& directory, const string& pattern = "*", const string& excludePattern = "", size_t depth = 1)
{
string sanitizedDirectory = OVPathHelper::NormalizeByExpandingTilde(directory);
OVWildcard expression(pattern);
OVWildcard negativeExpression(excludePattern);
vector<string> dirResult;
vector<string> fileResult;
struct dirent** namelist = NULL;
#ifndef WIN32
int count = scandir(sanitizedDirectory.c_str(), &namelist, NULL, NULL);
for (int index = 0; index < count; index++) {
struct dirent* entry = namelist[index];
bool isDir = entry->d_type == DT_DIR;
string name = entry->d_name;
#else
vector<pair<string, bool> > foundFiles;
WIN32_FIND_DATAW findData;
HANDLE findHandle = FindFirstFileW(OVUTF16::FromUTF8(OVPathHelper::PathCat(sanitizedDirectory, "*.*")).c_str(), &findData);
if (findHandle != INVALID_HANDLE_VALUE) {
foundFiles.push_back(pair<string, bool>(OVUTF8::FromUTF16(findData.cFileName), (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0));
while (FindNextFileW(findHandle, &findData))
{
foundFiles.push_back(pair<string, bool>(OVUTF8::FromUTF16(findData.cFileName), (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0));
}
FindClose(findHandle);
}
size_t count = foundFiles.size();
for (size_t index = 0; index < count; index++) {
string name = foundFiles[index].first;
bool isDir = foundFiles[index].second;
#endif
if ((!depth || depth > 1) && isDir && name != "." && name != "..") {
vector<string> subResult = Glob(OVPathHelper::PathCat(sanitizedDirectory, name), pattern, excludePattern, depth ? depth - 1 : 0);
vector<string>::iterator iter = subResult.begin();
for ( ; iter != subResult.end() ; iter++)
dirResult.push_back(*iter);
}
if (name != "." && name != ".." && expression.match(name) && !negativeExpression.match(name)) {
fileResult.push_back(OVPathHelper::PathCat(sanitizedDirectory, name));
}
#ifndef WIN32
free(entry);
#endif
}
#ifndef WIN32
if (count != -1)
free(namelist);
#endif
sort(dirResult.begin(), dirResult.end());
sort(fileResult.begin(), fileResult.end());
for (vector<string>::iterator iter = dirResult.begin() ; iter != dirResult.end(); iter++)
fileResult.push_back(*iter);
return fileResult;
}
static const string TempDirectory()
{
#ifndef WIN32
return string("/tmp");
#else
WCHAR path[MAX_PATH + 1];
GetTempPathW(MAX_PATH, path);
return OVUTF8::FromUTF16(path);
#endif
}
static const string GenerateTempFilename(const string& prefix = "temp")
{
string pattern = OVPathHelper::PathCat(TempDirectory(), prefix + "-" + "XXXXXXXX");
#ifndef WIN32
char *p = (char*)calloc(1, pattern.length() + 1);
strcpy(p, pattern.c_str());
char *r = mktemp(p);
if (!r) {
free(p);
return string();
}
string result = r;
free(p);
return result;
#else
wstring wp = OVUTF16::FromUTF8(pattern);
size_t length = wp.length() + 1;
wchar_t* p = (wchar_t*)calloc(1, length * sizeof(wchar_t));
wcscpy_s(p, length, wp.c_str());
errno_t err = _wmktemp_s(p, length);
if (err != 0) {
free(p);
return string();
}
string result = OVUTF8::FromUTF16(p);
free(p);
return result;
#endif
}
static const string UserHomeDirectory()
{
#ifndef WIN32
const char* homePath = getenv("HOME");
if (homePath)
return string(homePath);
return TempDirectory();
#else
WCHAR path[MAX_PATH + 1];
HRESULT error = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, path);
if (!error) {
return OVUTF8::FromUTF16(path);
}
return TempDirectory();
#endif
}
static const string UserApplicationDataDirectory(const string& applicationName)
{
#if defined(__APPLE__)
return OVPathHelper::PathCat(UserHomeDirectory(), OVPathHelper::PathCat("/Library/", applicationName));
#elif defined(WIN32)
WCHAR path[MAX_PATH + 1];
HRESULT error = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
if (!error) {
return OVPathHelper::PathCat(OVUTF8::FromUTF16(path), applicationName);
}
return OVPathHelper::PathCat(TempDirectory(), applicationName);
#else
return OVPathHelper::PathCat(UserHomeDirectory(), string(".") + applicationName);
#endif
}
static const string UserApplicationSupportDataDirectory(const string& applicationName)
{
#ifdef __APPLE__
return OVPathHelper::PathCat(UserHomeDirectory(), OVPathHelper::PathCat("/Library/Application Support", applicationName));
#else
return UserApplicationDataDirectory(applicationName);
#endif
}
static const string UserPreferencesDirectory(const string& applicationName)
{
#ifdef __APPLE__
return OVPathHelper::NormalizeByExpandingTilde("~/Library/Preferences");
#else
return UserApplicationDataDirectory(applicationName);
#endif
}
};
inline const string OVPathHelper::NormalizeByExpandingTilde(const string& path)
{
string newPath = Normalize(path);
if (newPath.length()) {
if (newPath[0] == '~') {
newPath = OVPathHelper::PathCat(OVDirectoryHelper::UserHomeDirectory(), newPath.substr(1, newPath.length()));
}
}
return newPath;
}
inline bool OVPathHelper::RemoveEverythingAtPath(const string& path)
{
if (!PathExists(path)) return false;
if (IsDirectory(path)) {
vector<string> files = OVDirectoryHelper::Glob(path, "*", "", 0);
vector<string>::iterator iter = files.begin();
for ( ; iter != files.end(); iter++) {
if (!RemoveEverythingAtPath(*iter))
return false;
}
#ifndef WIN32
return !rmdir(path.c_str());
#else
wstring wpath = OVUTF16::FromUTF8(path);
return RemoveDirectoryW(wpath.c_str()) == TRUE;
#endif
}
else {
#ifndef WIN32
return !unlink(path.c_str());
#else
wstring wpath = OVUTF16::FromUTF8(path);
return DeleteFileW(wpath.c_str()) == TRUE;
#endif
}
}
};
#endif

View File

@ -0,0 +1,92 @@
//
// OVFrameworkInfo.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVFrameworkVersion_h
#define OVFrameworkVersion_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#else
#include "OVBase.h"
#endif
#include <sstream>
namespace OpenVanilla {
using namespace std;
class OVFrameworkInfo {
public:
static unsigned int MajorVersion()
{
return c_MajorVersion;
}
static unsigned int MinorVersion()
{
return c_MinorVersion;
}
static unsigned int TinyVersion()
{
return c_TinyVersion;
}
static unsigned int Version()
{
return ((c_MajorVersion & 0xff) << 24) | ((c_MinorVersion & 0xff)<< 16) | (c_TinyVersion & 0xffff);
}
static unsigned int BuildNumber()
{
return c_FrameworkBuildNumber;
}
static const string VersionString(bool withBuildNumber = false)
{
stringstream s;
s << c_MajorVersion << "." << c_MinorVersion << "." << c_TinyVersion;
if (withBuildNumber)
s << "." << c_FrameworkBuildNumber;
return s.str();
}
static const string VersionStringWithBuildNumber()
{
return VersionString(true);
}
protected:
static const unsigned int c_MajorVersion;
static const unsigned int c_MinorVersion;
static const unsigned int c_TinyVersion;
static const unsigned int c_FrameworkBuildNumber;
};
};
#endif

View File

@ -0,0 +1,49 @@
//
// OVInputMethod.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVInputMethod_h
#define OVInputMethod_h
#if defined(__APPLE__)
#include <OpenVanilla/OVModule.h>
#else
#include "OVModule.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVInputMethod : public OVModule {
public:
virtual bool isInputMethod() const
{
return true;
}
};
};
#endif

View File

@ -0,0 +1,303 @@
//
// OVKey.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu and Weizhong Yang
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVKey_h
#define OVKey_h
namespace OpenVanilla {
using namespace std;
// keyCode() is 0 if receivedString() is a non-ASCII glyph/string
class OVKeyInterface : public OVBase {
public:
virtual const string receivedString() const = 0;
virtual unsigned int keyCode() const = 0;
virtual bool isAltPressed() const = 0;
virtual bool isOptPressed() const = 0;
virtual bool isCtrlPressed() const = 0;
virtual bool isShiftPressed() const = 0;
virtual bool isCommandPressed() const = 0;
virtual bool isNumLockOn() const = 0;
virtual bool isCapsLockOn() const = 0;
// a direct text key carries a composed glyph (or a string) that semantically differs from the intended keystroke
// (i.e. a half-width char stroke but with a composed, full-width char output)
virtual bool isDirectTextKey() const = 0;
};
class OVKeyImpl : public OVKeyInterface {
public:
virtual bool shouldDelete() const = 0;
virtual OVKeyImpl* copy() = 0;
};
class OVKey : public OVKeyInterface {
public:
OVKey(OVKeyImpl* keyImpl = 0)
: m_keyImpl(keyImpl)
{
}
OVKey(const OVKey& aKey)
{
m_keyImpl = aKey.m_keyImpl ? aKey.m_keyImpl->copy() : 0;
}
~OVKey()
{
if (m_keyImpl) {
if (m_keyImpl->shouldDelete()) {
delete m_keyImpl;
}
}
}
OVKey& operator=(const OVKey& aKey)
{
if (m_keyImpl) {
if (m_keyImpl->shouldDelete()) {
delete m_keyImpl;
}
m_keyImpl = 0;
}
m_keyImpl = aKey.m_keyImpl ? aKey.m_keyImpl->copy() : 0;
return *this;
}
virtual bool operator==(const OVKey& key) const
{
if (isAltPressed() == key.isAltPressed() && isOptPressed() == key.isOptPressed() && isCtrlPressed() == key.isCtrlPressed() && isShiftPressed() == key.isShiftPressed() && isCommandPressed() == key.isCommandPressed())
if (!keyCode() && !key.keyCode())
return receivedString() == key.receivedString();
else
return keyCode() == key.keyCode();
return false;
}
virtual bool operator<(const OVKey& key) const
{
if (keyCode() < key.keyCode()) return true;
if (keyCode() > key.keyCode()) return false;
if (!keyCode() && !key.keyCode()) {
if (receivedString() < key.receivedString()) return true;
if (receivedString() > key.receivedString()) return false;
}
if (isAltPressed() != key.isAltPressed()) {
if (key.isAltPressed()) return true;
if (isAltPressed()) return false;
}
if (isOptPressed() != key.isOptPressed()) {
if (key.isOptPressed()) return true;
if (isOptPressed()) return false;
}
if (isCtrlPressed() != key.isCtrlPressed()) {
if (key.isCtrlPressed()) return true;
if (isCtrlPressed()) return false;
}
if (isShiftPressed() != key.isShiftPressed()) {
if (key.isShiftPressed()) return true;
if (isShiftPressed()) return false;
}
if (isCommandPressed() != key.isCommandPressed()) {
if (key.isCommandPressed()) return true;
if (isCommandPressed()) return false;
}
if (isNumLockOn() != key.isNumLockOn()) {
if (key.isNumLockOn()) return true;
if (isNumLockOn()) return false;
}
if (isCapsLockOn() != key.isCapsLockOn()) {
if (key.isCapsLockOn()) return true;
if (isCapsLockOn()) return false;
}
return false;
}
public:
virtual const string receivedString() const
{
return m_keyImpl ? m_keyImpl->receivedString() : string();
}
virtual unsigned int keyCode() const
{
return m_keyImpl ? m_keyImpl->keyCode() : 0;
}
virtual bool isAltPressed() const
{
return m_keyImpl ? m_keyImpl->isAltPressed() : false;
}
virtual bool isOptPressed() const
{
return m_keyImpl ? m_keyImpl->isOptPressed() : false;
}
virtual bool isCtrlPressed() const
{
return m_keyImpl ? m_keyImpl->isCtrlPressed() : false;
}
virtual bool isShiftPressed() const
{
return m_keyImpl ? m_keyImpl->isShiftPressed() : false;
}
virtual bool isCommandPressed() const
{
return m_keyImpl ? m_keyImpl->isCommandPressed() : false;
}
virtual bool isNumLockOn() const
{
return m_keyImpl ? m_keyImpl->isNumLockOn() : false;
}
virtual bool isCapsLockOn() const
{
return m_keyImpl ? m_keyImpl->isCapsLockOn() : false;
}
virtual bool isDirectTextKey() const
{
return m_keyImpl ? m_keyImpl->isDirectTextKey() : false;
}
virtual bool isKeyCodePrintable() const
{
if (keyCode() >= 32 && keyCode() <= 126)
return true;
return false;
}
virtual bool isKeyCodeNumeric() const
{
if (keyCode() >= '0' && keyCode() <= '9')
return true;
return false;
}
virtual bool isKeyCodeAlpha() const
{
if (keyCode() >= 'A' && keyCode() <= 'Z' || keyCode() >= 'a' && keyCode() <= 'z')
return true;
return false;
}
virtual bool isCombinedFunctionKey() const
{
return isCtrlPressed() || isAltPressed() || isOptPressed() || isCommandPressed();
}
virtual bool isPrintable() const
{
size_t rssize = receivedString().size();
unsigned int code = keyCode();
if (!rssize)
return false;
if (rssize > 1)
return true;
return ((code < 128 && isprint((char)code)) || code > 128);
}
protected:
OVKeyImpl* m_keyImpl;
};
typedef vector<OVKey> OVKeyVector;
class OVKeyCode {
public:
enum {
Delete = 127,
Backspace = 8,
Up = 30,
Down = 31,
Left = 28,
Right = 29,
Home = 1,
End = 4,
PageUp = 11,
PageDown = 12,
Tab = 9,
Esc = 27,
Space = 32,
Return = 13,
Enter = Return,
LeftShift = 0x10001,
RightShift = 0x10002,
CapsLock = 0x10010,
MacEnter = 0x10020,
F1 = 0x11001,
F2 = 0x11002,
F3 = 0x11003,
F4 = 0x11004,
F5 = 0x11005,
F6 = 0x11006,
F7 = 0x11007,
F8 = 0x11008,
F9 = 0x11009,
F10 = 0x11010,
};
};
class OVKeyMask {
public:
enum {
Alt = 0x0001,
Opt = 0x0002,
AltOpt = 0x0003,
Ctrl = 0x0004,
Shift = 0x008,
Command = 0x0010,
NumLock = 0x0020,
CapsLock = 0x0040,
DirectText = 0x0080
};
};
};
#endif

View File

@ -0,0 +1,49 @@
//
// OVKeyPreprocessor.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVKeyPreprocessor_h
#define OVKeyPreprocessor_h
#if defined(__APPLE__)
#include <OpenVanilla/OVModule.h>
#else
#include "OVModule.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVKeyPreprocessor : public OVModule {
public:
virtual bool isPreprocessor() const
{
return true;
}
};
};
#endif

View File

@ -0,0 +1,175 @@
//
// OVKeyValueMap.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVKeyValueMap_h
#define OVKeyValueMap_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#else
#include "OVBase.h"
#endif
#include <sstream>
namespace OpenVanilla {
using namespace std;
class OVKeyValueMapInterface : public OVBase {
public:
virtual bool isReadOnly() = 0;
virtual bool setKeyStringValue(const string& key, const string& value) = 0;
virtual bool hasKey(const string& key) = 0;
virtual const string stringValueForKey(const string& key) = 0;
virtual bool setKeyIntValue(const string& key, int value)
{
stringstream sstr;
sstr << value;
return setKeyStringValue(key, sstr.str());
}
virtual bool setKeyBoolValue(const string& key, bool value)
{
if (value)
return setKeyStringValue(key, "true");
return setKeyStringValue(key, "false");
}
virtual int intValueForKey(const string& key)
{
string value = stringValueForKey(key);
return atoi(value.c_str());
}
virtual const string stringValueForKeyWithDefault(const string& key, const string& defaultValue = "", bool setIfNotFound = true)
{
if (hasKey(key))
return stringValueForKey(key);
if (setIfNotFound)
setKeyStringValue(key, defaultValue);
return defaultValue;
}
virtual const string operator[](const string& key)
{
return stringValueForKey(key);
}
virtual bool isKeyTrue(const string& key)
{
if (!hasKey(key))
return false;
string value = stringValueForKey(key);
if (atoi(value.c_str()) > 0)
return true;
if (value == "true")
return true;
return false;
}
};
class OVKeyValueMapImpl : public OVKeyValueMapInterface {
public:
virtual bool shouldDelete() = 0;
virtual OVKeyValueMapImpl* copy() = 0;
};
class OVKeyValueMap : public OVKeyValueMapInterface {
public:
OVKeyValueMap(OVKeyValueMapImpl* keyValueMapImpl = 0)
: m_keyValueMapImpl(keyValueMapImpl)
{
}
OVKeyValueMap(const OVKeyValueMap& aKeyValueMap)
{
m_keyValueMapImpl = aKeyValueMap.m_keyValueMapImpl ? aKeyValueMap.m_keyValueMapImpl->copy() : 0;
}
~OVKeyValueMap()
{
if (m_keyValueMapImpl) {
if (m_keyValueMapImpl->shouldDelete()) {
delete m_keyValueMapImpl;
}
}
}
OVKeyValueMap& operator=(const OVKeyValueMap& aKeyValueMap)
{
if (m_keyValueMapImpl) {
if (m_keyValueMapImpl->shouldDelete()) {
delete m_keyValueMapImpl;
}
m_keyValueMapImpl = 0;
}
m_keyValueMapImpl = aKeyValueMap.m_keyValueMapImpl ? aKeyValueMap.m_keyValueMapImpl->copy() : 0;
return *this;
}
public:
virtual bool isReadOnly()
{
return m_keyValueMapImpl ? m_keyValueMapImpl->isReadOnly() : true;
}
virtual bool setKeyStringValue(const string& key, const string& value)
{
return m_keyValueMapImpl ? m_keyValueMapImpl->setKeyStringValue(key, value) : false;
}
virtual bool hasKey(const string& key)
{
return m_keyValueMapImpl ? m_keyValueMapImpl->hasKey(key) : false;
}
virtual const string stringValueForKey(const string& key)
{
return m_keyValueMapImpl ? m_keyValueMapImpl->stringValueForKey(key) : string();
}
virtual const string stringValueForKeyWithDefault(const string& key, const string& defaultValue = "", bool setIfNotFound = true)
{
return m_keyValueMapImpl ? m_keyValueMapImpl->stringValueForKeyWithDefault(key, defaultValue, setIfNotFound) : string();
}
protected:
OVKeyValueMapImpl* m_keyValueMapImpl;
};
};
#endif

View File

@ -0,0 +1,50 @@
//
// OVLoaderBase.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVLoaderBase_h
#define OVLoaderBase_h
#if defined(__APPLE__)
#include <OpenVanilla/OVModule.h>
#else
#include "OVModule.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVLoader : public OVBase {
public:
virtual OVLoaderService* loaderService() = 0;
virtual OVModule* moduleForIdentifier(const string& identifier) = 0;
virtual vector<string> moduleIdentifiers() = 0;
virtual vector<string> moduleIdentifiersForConditions(bool preprocessor, bool inputMethod, bool outputFilter) = 0;
};
};
#endif

View File

@ -0,0 +1,120 @@
//
// OVLoaderService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVLoaderService_h
#define OVLoaderService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#include <OpenVanilla/OVDatabaseService.h>
#include <OpenVanilla/OVEncodingService.h>
#include <OpenVanilla/OVKey.h>
#else
#include "OVBase.h"
#include "OVDatabaseService.h"
#include "OVEncodingService.h"
#include "OVKey.h"
#endif
#include <iostream>
#include <sstream>
namespace OpenVanilla {
using namespace std;
class OVLogEmitter : public OVBase {
public:
virtual const string sectionName() const = 0;
virtual void setSectionName(const string& sectionName) = 0;
virtual void emitLog(const string& logEntry) = 0;
};
class OVLogStringBuffer : public stringbuf {
public:
OVLogStringBuffer(OVLogEmitter* logEmitter = 0)
: m_logEmitter(logEmitter)
{
}
virtual int sync() {
if (str().length()) {
if (m_logEmitter)
m_logEmitter->emitLog(str());
else
cerr << "Log: " << str();
str(string());
}
// clear the buffer
return 0;
}
virtual OVLogEmitter* logEmitter() const
{
return m_logEmitter;
}
virtual void setLogEmitter(OVLogEmitter* logEmitter)
{
m_logEmitter = logEmitter;
}
protected:
OVLogEmitter* m_logEmitter;
};
class OVLoaderService : public OVBase {
public:
virtual void beep() = 0;
virtual void notify(const string& message) = 0;
virtual void HTMLNotify(const string& content) = 0;
virtual const string locale() const = 0;
virtual const OVKey makeOVKey(int characterCode, bool alt = false, bool opt = false, bool ctrl = false, bool shift = false, bool command = false, bool capsLock = false, bool numLock = false) = 0;
virtual const OVKey makeOVKey(const string& receivedString, bool alt = false, bool opt = false, bool ctrl = false, bool shift = false, bool command = false, bool capsLock = false, bool numLock = false) = 0;
virtual ostream& logger(const string& sectionName = "") = 0;
virtual OVDatabaseService* defaultDatabaseService() = 0;
virtual OVDatabaseService* CINDatabaseService() = 0;
virtual OVDatabaseService* SQLiteDatabaseService() = 0;
virtual OVEncodingService* encodingService() = 0;
virtual void __reserved1(const string&) = 0;
virtual void __reserved2(const string&) = 0;
virtual void __reserved3(const string&) = 0;
virtual void __reserved4(const string&) = 0;
virtual const string __reserved5() const = 0;
virtual void __reserved6(const string&) = 0;
virtual void __reserved7(const string&, const string &) = 0;
virtual void* __reserved8(const string&) = 0;
};
};
#endif

View File

@ -0,0 +1,136 @@
//
// OVLocalization.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVLocalization_h
#define OVLocalization_h
#include <string>
#include <map>
#include "OVStringHelper.h"
#include "OVWildcard.h"
namespace OpenVanilla {
using namespace std;
class OVLocale {
public:
static const string POSIXLocaleID(const string& locale)
{
string n = OVStringHelper::StringByReplacingOccurrencesOfStringWithString(locale, "-", "_");
if (OVWildcard::Match(n, "zh_Hant")) {
return "zh_TW";
}
if (OVWildcard::Match(n, "zh_Hans")) {
return "zh_CN";
}
if (OVWildcard::Match(n, "zh_HK")) {
return "zh_TW";
}
if (OVWildcard::Match(n, "zh_SG")) {
return "zh_CN";
}
if (OVWildcard::Match(n, "en_*")) {
return "en";
}
return locale;
}
};
template<class T> class OVLocalization {
public:
static const void SetDefaultLocale(const string& locale)
{
SharedInstance()->m_defaultLocale = locale.length() ? OVLocale::POSIXLocaleID(locale) : string("en");
}
static const string S(const string& locale, const string& text)
{
return SharedInstance()->m_table(locale, text);
}
static const string S(const string& text)
{
return SharedInstance()->m_table(SharedInstance()->m_defaultLocale, text);
}
protected:
static OVLocalization<T>* SharedInstance()
{
static OVLocalization<T>* instance = 0;
if (!instance) {
instance = new OVLocalization<T>;
}
return instance;
}
OVLocalization<T>()
: m_defaultLocale("en")
{
}
T m_table;
string m_defaultLocale;
};
class OVLocalizationStringTable {
public:
const string operator()(const string& locale, const string& text) const
{
// maybe we'll have fallback logic later here
map<string, map<string, string> >::const_iterator i = m_table.find(locale);
if (i == m_table.end()) {
return text;
}
map<string, string>::const_iterator j = (*i).second.find(text);
if (j == (*i).second.end()) {
return text;
}
return (*j).second;
}
protected:
void add(const string& locale, const string& original, const string& localized)
{
m_table[locale][original] = localized;
}
map<string, map<string, string> > m_table;
};
};
#endif

View File

@ -0,0 +1,146 @@
//
// OVModule.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVModule_h
#define OVModule_h
#if defined(__APPLE__)
#include <OpenVanilla/OVEventHandlingContext.h>
#include <OpenVanilla/OVKeyValueMap.h>
#include <OpenVanilla/OVPathInfo.h>
#else
#include "OVEventHandlingContext.h"
#include "OVKeyValueMap.h"
#include "OVPathInfo.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVModule : public OVBase {
public:
OVModule()
: m_initialized(false)
, m_usable(false)
{
}
virtual bool isInitialized() const
{
return m_initialized;
}
virtual bool isUsable() const
{
return m_usable;
}
virtual bool isPreprocessor() const
{
return false;
}
virtual bool isInputMethod() const
{
return false;
}
virtual bool isOutputFilter() const
{
return false;
}
virtual bool isAroundFilter() const
{
return false;
}
// the smaller it gets, the closer the the filter gets to the commit event
virtual int suggestedOrder() const
{
return 0;
}
virtual OVEventHandlingContext* createContext()
{
return 0;
}
virtual const string identifier() const = 0;
virtual const string localizedName(const string& locale)
{
return identifier();
}
virtual bool moduleInitialize(OVPathInfo* pathInfo, OVLoaderService* loaderService)
{
if (m_initialized)
return false;
m_usable = initialize(pathInfo, loaderService);
m_initialized = true;
return m_usable;
}
virtual bool initialize(OVPathInfo* pathInfo, OVLoaderService* loaderService)
{
return true;
}
virtual void finalize()
{
}
virtual void loadConfig(OVKeyValueMap* moduleConfig, OVLoaderService* loaderService)
{
}
virtual void saveConfig(OVKeyValueMap* moduleConfig, OVLoaderService* loaderService)
{
}
enum AroundFilterDisplayOption {
ShownAsPreprocessor,
ShownAsOutputFilter,
ShownAsBoth
};
// around filter modules need to tell loader how it wishes to be placed in the menu
virtual AroundFilterDisplayOption aroundFilterPreferredDisplayOption()
{
return ShownAsBoth;
}
protected:
bool m_initialized;
bool m_usable;
};
};
#endif

View File

@ -0,0 +1,100 @@
//
// OVModulePackage.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVModulePackage_h
#define OVModulePackage_h
#if defined(__APPLE__)
#include <OpenVanilla/OVFrameworkInfo.h>
#include <OpenVanilla/OVModule.h>
#else
#include "OVFrameworkInfo.h"
#include "OVModule.h"
#endif
#ifdef WIN32
#define OVEXPORT __declspec(dllexport)
#else
#define OVEXPORT
#endif
namespace OpenVanilla {
using namespace std;
class OVModuleClassWrapperBase : public OVBase {
public:
virtual OVModule* newModule()
{
// this member function can't be abstract, or vector<OVModuleClassWrapperBase> wouldn't instantiate under VC++ 2005
return 0;
}
};
template<class T> class OVModuleClassWrapper : public OVModuleClassWrapperBase {
public:
virtual OVModule* newModule()
{
return new T;
}
};
// we encourage people to do the real initialization in initialize
class OVModulePackage : OVBase {
public:
~OVModulePackage()
{
vector<OVModuleClassWrapperBase*>::iterator iter = m_moduleVector.begin();
for ( ; iter != m_moduleVector.end(); ++iter)
delete *iter;
}
virtual bool initialize(OVPathInfo* , OVLoaderService* loaderService)
{
// in your derived class, add class wrappers to m_moduleVector
return true;
}
virtual void finalize()
{
}
virtual size_t numberOfModules(OVLoaderService*)
{
return m_moduleVector.size();
}
virtual OVModule* moduleAtIndex(size_t index, OVLoaderService*)
{
if (index > m_moduleVector.size()) return 0;
return m_moduleVector[index]->newModule();
}
protected:
vector<OVModuleClassWrapperBase*> m_moduleVector;
};
};
#endif

View File

@ -0,0 +1,49 @@
//
// OVOutputFilter.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVOutputFilter_h
#define OVOutputFilter_h
#if defined(__APPLE__)
#include <OpenVanilla/OVModule.h>
#else
#include "OVModule.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVOutputFilter : public OVModule {
public:
virtual bool isOutputFilter() const
{
return true;
}
};
};
#endif

View File

@ -0,0 +1,63 @@
//
// OVPathInfo.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVPathInfo_h
#define OVPathInfo_h
#if defined(__APPLE__)
#include <OpenVanilla/OVFileHelper.h>
#else
#include "OVFileHelper.h"
#endif
namespace OpenVanilla {
using namespace std;
struct OVPathInfo {
string loadedPath;
string resourcePath;
string writablePath;
static const OVPathInfo DefaultPathInfo() {
string tmpdir = OVDirectoryHelper::TempDirectory();
OVPathInfo pathInfo;
pathInfo.loadedPath = tmpdir;
pathInfo.resourcePath = tmpdir;
pathInfo.writablePath = tmpdir;
return pathInfo;
}
};
inline ostream& operator<<(ostream& stream, const OVPathInfo& info)
{
stream << "OVPathInfo = (loaded path = " << info.loadedPath << ", resource path = " << info.resourcePath << ", writable path = " << info.writablePath << ")";
return stream;
}
};
#endif

View File

@ -0,0 +1,249 @@
//
// OVSQLiteDatabaseService.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVSQLiteDatabaseService_h
#define OVSQLiteDatabaseService_h
#if defined(__APPLE__)
#include <OpenVanilla/OVDatabaseService.h>
#include <OpenVanilla/OVSQLiteWrapper.h>
#include <OpenVanilla/OVWildcard.h>
#else
#include "OVDatabaseService.h"
#include "OVSQLiteWrapper.h"
#include "OVWildcard.h"
#endif
namespace OpenVanilla {
using namespace std;
class OVSQLiteHelper {
public:
static const pair<string, string> SQLiteStringFromWildcard(const OVWildcard& wildcard)
{
const string& expression = wildcard.expression();
string sqlstr;
char mOC = wildcard.matchOneChar();
char mZOMC = wildcard.matchZeroOrMoreChar();
char escChar = mZOMC ? mZOMC : mOC;
for (string::const_iterator iter = expression.begin() ; iter != expression.end() ; ++iter) {
if (*iter == mOC) {
sqlstr += '_';
}
else if (*iter == mZOMC) {
sqlstr += '%';
}
else if (*iter == '_') {
sqlstr += escChar;
sqlstr += '_';
}
else if (*iter == '%') {
sqlstr += escChar;
sqlstr += '%';
}
else {
sqlstr += *iter;
}
}
return pair<string, string>(sqlstr, string(1, escChar));
}
};
class OVSQLiteDatabaseService;
class OVSQLiteKeyValueDataTable : public OVKeyValueDataTableInterface {
public:
virtual const vector<string> valuesForKey(const string& key);
virtual const vector<pair<string, string> > valuesForKey(const OVWildcard& expression);
virtual const string valueForProperty(const string& property);
virtual const vector<string> keysForValue(const string& value);
protected:
OVSQLiteDatabaseService* m_source;
string m_tableName;
friend class OVSQLiteDatabaseService;
OVSQLiteKeyValueDataTable(OVSQLiteDatabaseService* source, const string& tableName)
: m_source(source)
, m_tableName(tableName)
{
}
};
class OVSQLiteDatabaseService : public OVDatabaseService {
public:
~OVSQLiteDatabaseService()
{
if (m_ownsConnection)
delete m_connection;
}
virtual const vector<string> tables(const OVWildcard& filter = string("*"))
{
pair<string, string> exp = OVSQLiteHelper::SQLiteStringFromWildcard(filter);
vector<string> result;
OVSQLiteStatement* statement = m_connection->prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE %Q ESCAPE %Q ORDER BY name", exp.first.c_str(), exp.second.c_str());
if (statement) {
while (statement->step() == SQLITE_ROW) {
result.push_back(statement->textOfColumn(0));
}
delete statement;
}
return result;
}
virtual bool tableSupportsValueToKeyLookup(const string &tableName)
{
return true;
}
virtual OVKeyValueDataTableInterface* createKeyValueDataTableInterface(const string& name, bool suggestedCaseSensitivity = false)
{
return new OVSQLiteKeyValueDataTable(this, name);
}
virtual const string valueForPropertyInTable(const string& property, const string& name)
{
OVSQLiteStatement* statement = m_connection->prepare("SELECT VALUE FROM %Q WHERE KEY = ?", name.c_str());
string result;
if (statement) {
statement->bindTextToColumn(string(OVPropertyStringInternalPrefix) + property, 1);
if (statement->step() == SQLITE_ROW) {
result = statement->textOfColumn(0);
while (statement->step() == SQLITE_ROW) ;
}
delete statement;
}
return result;
}
virtual const string filename()
{
return m_connection->filename();
}
static OVSQLiteDatabaseService* Create(const string& filename = ":memory:")
{
OVSQLiteConnection* connection = OVSQLiteConnection::Open(filename);
if (!connection)
return 0;
return new OVSQLiteDatabaseService(connection, true);
}
static OVSQLiteDatabaseService* ServiceWithExistingConnection(OVSQLiteConnection* connection, bool ownsConnection = false)
{
return new OVSQLiteDatabaseService(connection, ownsConnection);
}
OVSQLiteConnection* connection()
{
return m_connection;
}
protected:
friend class OVSQLiteKeyValueDataTable;
OVSQLiteDatabaseService(OVSQLiteConnection* connection, bool ownsConnection = false)
: m_connection(connection)
, m_ownsConnection(ownsConnection)
{
}
OVSQLiteConnection* m_connection;
bool m_ownsConnection;
};
inline const vector<string> OVSQLiteKeyValueDataTable::valuesForKey(const string& key)
{
vector<string> result;
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT value FROM %Q WHERE key = %Q", m_tableName.c_str(), key.c_str());
if (statement) {
while (statement->step() == SQLITE_ROW) {
result.push_back(statement->textOfColumn(0));
}
delete statement;
}
return result;
}
inline const vector<string> OVSQLiteKeyValueDataTable::keysForValue(const string& value)
{
vector<string> result;
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT key FROM %Q WHERE value = %Q", m_tableName.c_str(), value.c_str());
if (statement) {
while (statement->step() == SQLITE_ROW) {
string key = statement->textOfColumn(0);
// we don't want property get into it
if (!OVWildcard::Match(key, OVPropertyStringInternalPrefix "*")) {
result.push_back(key);
}
}
delete statement;
}
return result;
}
inline const vector<pair<string, string> > OVSQLiteKeyValueDataTable::valuesForKey(const OVWildcard& expression)
{
pair<string, string> exp = OVSQLiteHelper::SQLiteStringFromWildcard(expression);
vector<pair<string, string> > result;
OVSQLiteStatement* statement = m_source->connection()->prepare("SELECT key, value FROM %Q WHERE key like %Q escape %Q", m_tableName.c_str(), exp.first.c_str(), exp.second.c_str());
if (statement) {
while (statement->step() == SQLITE_ROW) {
result.push_back(pair<string, string>(statement->textOfColumn(0), statement->textOfColumn(1)));
}
delete statement;
}
return result;
}
inline const string OVSQLiteKeyValueDataTable::valueForProperty(const string& property)
{
return m_source->valueForPropertyInTable(property, m_tableName);
}
};
#endif

View File

@ -0,0 +1,278 @@
//
// OVSQLiteWrapper.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVSQLite3Wrapper
#define OVSQLite3Wrapper
#include <sqlite3.h>
#if defined(__APPLE__)
#include <OpenVanilla/OpenVanilla.h>
#else
#include "OpenVanilla.h"
#endif
// For status codes (SQLITE_OK, SQLITE_ERROR, etc.), please refer to sqlite3.h
namespace OpenVanilla {
using namespace std;
class OVSQLiteStatement;
class OVSQLiteConnection {
public:
// remember to manage the object returned by this class member function
static OVSQLiteConnection* Open(const string& filename = ":memory:");
~OVSQLiteConnection();
int lastError();
const char* lastErrorMessage();
int execute(const char* sqlcmd, ...);
OVSQLiteStatement* prepare(const char* sqlcmd, ...);
// helper for table creation and detection
bool hasTable(const string& tableName);
bool dropTable(const string& tableName);
bool createTable(const string& tableName, const string& columnString = "key, value", bool dropIfExists = false);
bool createIndexOnTable(const string& indexName, const string& tableName, const string& indexColumns = "key");
sqlite3* connection();
const string filename();
protected:
sqlite3* m_connection;
string m_filename;
OVSQLiteConnection(sqlite3* connection, const string& filename);
};
class OVSQLiteStatement {
public:
~OVSQLiteStatement();
int reset();
// *nota bene* column starts from 1 !
int bindTextToColumn(const char*str, int column);
int bindTextToColumn(const string& str, int column);
int bindIntToColumn(int value, int column);
int bindDoubleToColumn(double value, int column);
int step();
int columnCount();
const char* textOfColumn(int column);
int intOfColumn(int column);
double doubleOfColumn(int column);
protected:
sqlite3_stmt* m_statement;
friend class OVSQLiteConnection;
OVSQLiteStatement(sqlite3_stmt* statement);
};
inline sqlite3* OVSQLiteConnection::connection()
{
return m_connection;
}
inline OVSQLiteConnection* OVSQLiteConnection::Open(const string& filename)
{
sqlite3* connection;
if (sqlite3_open(filename.c_str(), &connection) != SQLITE_OK)
return 0;
if (!connection)
return 0;
return new OVSQLiteConnection(connection, filename);
}
inline OVSQLiteConnection::OVSQLiteConnection(sqlite3* connection, const string& filename)
: m_connection(connection)
, m_filename(filename)
{
}
inline OVSQLiteConnection::~OVSQLiteConnection()
{
int result = sqlite3_close(m_connection);
if (result) {
;
}
}
inline const string OVSQLiteConnection::filename()
{
return m_filename;
}
inline int OVSQLiteConnection::lastError()
{
return sqlite3_errcode(m_connection);
}
inline const char* OVSQLiteConnection::lastErrorMessage()
{
return sqlite3_errmsg(m_connection);
}
inline int OVSQLiteConnection::execute(const char* sqlcmd, ...)
{
va_list l;
va_start(l, sqlcmd);
char* cmd = sqlite3_vmprintf(sqlcmd, l);
va_end(l);
int result = sqlite3_exec(m_connection, cmd, NULL, NULL, NULL);
sqlite3_free(cmd);
return result;
}
inline OVSQLiteStatement* OVSQLiteConnection::prepare(const char* sqlcmd, ...)
{
va_list l;
va_start(l, sqlcmd);
char* cmd = sqlite3_vmprintf(sqlcmd, l);
va_end(l);
sqlite3_stmt* stmt;
OVSQLiteStatement* result = 0;
const char* remainingSt = 0;
if (sqlite3_prepare_v2(m_connection, cmd, -1, &stmt, &remainingSt) == SQLITE_OK)
result = new OVSQLiteStatement(stmt);
sqlite3_free(cmd);
return result;
}
inline bool OVSQLiteConnection::hasTable(const string& tableName)
{
bool result = false;
OVSQLiteStatement* statement = prepare("SELECT name FROM sqlite_master WHERE name = %Q", tableName.c_str());
if (statement) {
if (statement->step() == SQLITE_ROW) {
result = true;
while (statement->step() == SQLITE_ROW) ;
}
delete statement;
}
return result;
}
inline bool OVSQLiteConnection::dropTable(const string& tableName)
{
return SQLITE_OK == execute("DROP TABLE %Q", tableName.c_str());
}
inline bool OVSQLiteConnection::createTable(const string& tableName, const string& columnString, bool dropIfExists)
{
if (hasTable(tableName)) {
if (dropIfExists) {
if (!dropTable(tableName))
return false;
}
else {
return false;
}
}
return SQLITE_OK == execute("CREATE TABLE %Q (%s)", tableName.c_str(), columnString.c_str());
}
inline bool OVSQLiteConnection::createIndexOnTable(const string& indexName, const string& tableName, const string& indexColumns)
{
return SQLITE_OK == execute("CREATE INDEX %Q on %Q (%s)", indexName.c_str(), tableName.c_str(), indexColumns.c_str());
}
inline OVSQLiteStatement::OVSQLiteStatement(sqlite3_stmt* statement)
: m_statement(statement)
{
}
inline OVSQLiteStatement::~OVSQLiteStatement()
{
sqlite3_finalize(m_statement);
}
inline int OVSQLiteStatement::reset()
{
return sqlite3_reset(m_statement);
}
inline int OVSQLiteStatement::bindTextToColumn(const char* str, int column)
{
return sqlite3_bind_text(m_statement, column, str, -1, SQLITE_TRANSIENT);
}
inline int OVSQLiteStatement::bindTextToColumn(const string& str, int column)
{
return bindTextToColumn(str.c_str(), column);
}
inline int OVSQLiteStatement::bindIntToColumn(int value, int column)
{
return sqlite3_bind_int(m_statement, column, value);
}
inline int OVSQLiteStatement::bindDoubleToColumn(double value, int column)
{
return sqlite3_bind_double(m_statement, column, value);
}
inline int OVSQLiteStatement::step()
{
return sqlite3_step(m_statement);
}
inline int OVSQLiteStatement::columnCount()
{
return sqlite3_column_count(m_statement);
}
inline const char* OVSQLiteStatement::textOfColumn(int column)
{
return (const char*)sqlite3_column_text(m_statement, column);
}
inline int OVSQLiteStatement::intOfColumn(int column)
{
return sqlite3_column_int(m_statement, column);
}
inline double OVSQLiteStatement::doubleOfColumn(int column)
{
return sqlite3_column_double(m_statement, column);
}
};
#endif

View File

@ -0,0 +1,218 @@
//
// OVStringHelper.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVStringHelper_h
#define OVStringHelper_h
#include <string>
#include <sstream>
#include <vector>
namespace OpenVanilla {
using namespace std;
class OVStringHelper {
public:
static const vector<string> SplitBySpacesOrTabsWithDoubleQuoteSupport(const string& text)
{
vector<string> result;
size_t index = 0, last = 0, length = text.length();
while (index < length) {
if (text[index] == '\"') {
index++;
string tmp;
while (index < length) {
if (text[index] == '\"') {
index++;
break;
}
if (text[index] == '\\' && index + 1 < length) {
index++;
char c = text[index];
switch (c) {
case 'r':
tmp += '\r';
break;
case 'n':
tmp += '\n';
break;
case '\"':
tmp += '\"';
break;
case '\\':
tmp += '\\';
break;
}
}
else {
tmp += text[index];
}
index++;
}
result.push_back(tmp);
}
if (text[index] != ' ' && text[index] != '\t') {
last = index;
while (index < length) {
if (text[index] == ' ' || text[index] == '\t') {
if (index - last)
result.push_back(text.substr(last, index - last));
break;
}
index++;
}
if (index == length && index - last)
result.push_back(text.substr(last, index - last));
}
index++;
}
return result;
}
static const vector<string> SplitBySpacesOrTabs(const string& text)
{
vector<string> result;
size_t index = 0, last = 0, length = text.length();
while (index < length) {
if (text[index] != ' ' && text[index] != '\t') {
last = index;
while (index < length) {
if (text[index] == ' ' || text[index] == '\t') {
if (index - last)
result.push_back(text.substr(last, index - last));
break;
}
index++;
}
if (index == length && index - last)
result.push_back(text.substr(last, index - last));
}
index++;
}
return result;
}
static const vector<string> Split(const string& text, char c)
{
vector<std::string> result;
size_t index = 0, last = 0, length = text.length();
while (index < length) {
while (index < length) {
if (text[index] == c) {
result.push_back(text.substr(last, index - last));
last = index + 1;
break;
}
index++;
}
index++;
}
if (last <= index) {
result.push_back(text.substr(last, index - last));
}
return result;
}
// named after Cocoa's NSString -stringByReplacingOccurrencesOfString:WithString:, horrible
static const string StringByReplacingOccurrencesOfStringWithString(const string& source, const string& substr, const string& replacement)
{
if (!substr.length())
return source;
size_t pos;
if ((pos = source.find(substr)) >= source.length())
return source;
return source.substr(0, pos) + replacement + StringByReplacingOccurrencesOfStringWithString(source.substr(pos + substr.length()), substr, replacement);
}
static const string Join(const vector<string>& vec)
{
string result;
for (vector<string>::const_iterator iter = vec.begin(); iter != vec.end() ; ++iter)
result += *iter;
return result;
}
static const string Join(const vector<string>& vec, const string& separator)
{
return Join(vec.begin(), vec.end(), separator);
}
static const string Join(const vector<string>& vec, size_t from, size_t size, const string& separator)
{
return Join(vec.begin() + from, vec.begin() + from + size, separator);
}
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
{
string result;
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
result += *iter;
if (++iter != end)
result += separator;
}
return result;
}
static const string PercentEncode(const string& text)
{
stringstream sst;
sst << hex;
for (string::const_iterator i = text.begin() ; i != text.end() ; ++i) {
if ((*i >= '0' && *i <= '9') || (*i >= 'A' && *i <= 'Z') || (*i >= 'a' && *i <= 'z') || *i == '-' || *i == '_' || *i == '.' || *i == '~') {
sst << (char)*i;
}
else {
sst << '%';
sst.width(2);
sst.fill('0');
unsigned char c = *i;
sst << (unsigned int)c;
}
}
return sst.str();
}
};
}
#endif

View File

@ -0,0 +1,102 @@
//
// OVTextBuffer.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVTextBuffer_h
#define OVTextBuffer_h
#if defined(__APPLE__)
#include <OpenVanilla/OVBase.h>
#else
#include "OVBase.h"
#endif
namespace OpenVanilla {
using namespace std;
// Terminologies:
// * Text buffer = a generic term
// * Composing text = composing buffer = composition buffer
// In Windows speak, "composition buffer" doesn't contain reading
// (Reading is a separate concept in Windows)
// In Mac speak, "composing buffer" == composing text + reading text
// * Reading text = currently in-wait-state radicals
// * Pre-edit, pre-edit area or pre-edit buffer (X11 speak) = composing text + reading
// Mac's composing buffer is actually pre-edit in this sense
class OVTextBuffer : public OVBase {
public:
virtual void clear() = 0;
virtual void setText(const string& text) = 0;
virtual void appendText(const string& text, bool moveCursor = true) = 0;
// when the text buffer is committed, the buffer itself, along with settings like cursor, and tooltip (for both composing text and reading text), highlight, word segments, and suggested display style (for reading text) are cleared; the combined committed string will be available at composedCommittedText()
virtual void commit() = 0;
virtual void commitAsTextSegment() = 0;
virtual void commit(const string& text) = 0;
virtual void commitAsTextSegment(const string& text) = 0;
virtual void updateDisplay() = 0;
virtual bool isEmpty() const = 0;
virtual size_t codePointCount() const = 0;
virtual const string codePointAt(size_t index) const = 0;
virtual const string composedText() const = 0;
virtual const string composedCommittedText() const = 0;
virtual const vector<string> composedCommittedTextSegments() const = 0;
// Composing text (composing buffer, composition buffer)-only members
public:
typedef pair<size_t, size_t> RangePair;
// composing buffer should support these four, but reading buffer doesn't need to (anyway it's meaningless)
virtual void setCursorPosition(size_t position) = 0;
virtual size_t cursorPosition() const = 0;
virtual void showToolTip(const string& text) = 0;
virtual void clearToolTip() = 0;
// implementation details: composing buffer might support this, but reading buffer doesn't
virtual void setHighlightMark(const RangePair& range) = 0;
// word segments: on Windows, this is an independent (though application-dependent) feature, on Mac OS X, word segments cannot overlap with the highlight mark, and also, when the highlight mark is on, the cursor is off
virtual void setWordSegments(const vector<RangePair>& segments) = 0;
// Reading text only members
public:
enum ReadingTextStyle {
Horizontal = 0,
Vertical = 1
};
// this is only for the reading buffer, and is not a required implementation
virtual void setSuggestedReadingTextStyle(ReadingTextStyle style) = 0;
virtual ReadingTextStyle defaultReadingTextStyle() const = 0;
};
};
#endif

View File

@ -0,0 +1,194 @@
//
// OVUTF8Helper.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVUTF8Helper_h
#define OVUTF8Helper_h
#include <cstddef>
#include <string>
#include <vector>
#include <iostream>
namespace OpenVanilla {
using namespace std;
class OVUTF8Helper {
public:
static const vector<string> SplitStringByCodePoint(const string& utf8String)
{
size_t index, length = utf8String.length();
vector<string> result;
for (index = 0; index < length; index++) {
unsigned char c = utf8String[index];
if (!(c & 0x80)) {
result.push_back(utf8String.substr(index, 1));
}
else if ((c & (0x80 | 0x40)) && !(c & 0x20)) {
result.push_back(utf8String.substr(index, 2));
index += 1;
}
else if ((c & (0x80 | 0x40 | 0x20)) && !(c & 0x10)) {
result.push_back(utf8String.substr(index, 3));
index += 2;
}
else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) && !(c & 0x8)) {
result.push_back(utf8String.substr(index, 4));
index += 3;
}
}
return result;
}
static const string CombineCodePoints(const vector<string>& codePoints)
{
string result;
for (vector<string>::const_iterator iter = codePoints.begin(); iter != codePoints.end() ; ++iter)
result += *iter;
return result;
}
static const wstring ConvertStringToUTF16WideString(const string& utf8String)
{
wstring wideString;
vector<string> charVector = OVUTF8Helper::SplitStringByCodePoint(utf8String);
size_t length = charVector.size();
for (size_t index = 0; index < length; index++)
{
unsigned int codePoint = OVUTF8Helper::CodePointFromSingleUTF8String(charVector[index]);
if (codePoint < 0x10000) {
wideString += (wchar_t)codePoint;
}
else {
const unsigned int leadOffset = 0xD800 - (0x10000 >> 10);
unsigned int lead = leadOffset + (codePoint >> 10);
unsigned int trail = 0xdc00 + (codePoint & 0x3ff);
wideString += (wchar_t)lead;
wideString += (wchar_t)trail;
}
}
return wideString;
}
static const string StringFromUTF16WideString(const wstring& utf16WideString)
{
string utf8String;
size_t length = utf16WideString.length();
unsigned int u16;
for (size_t index = 0; index < length; index++) {
u16 = utf16WideString[index];
if (u16 >= 0xd800 && u16 <= 0xdbff) {
if (index + 1 < length) {
unsigned int trailing = utf16WideString[index + 1];
if (trailing >= 0xdc00 && trailing <= 0xdfff) {
index++;
const unsigned int surrogateOffset = 0x10000 - (0xD800 << 10) - 0xDC00;
unsigned int codePoint = (u16 << 10) + trailing + surrogateOffset;
utf8String += OVUTF8Helper::SingleUTF8StringFromCodePoint(codePoint);
}
}
}
else if (!(u16 >= 0xdc00 && u16 <= 0xdfff))
{
utf8String += OVUTF8Helper::SingleUTF8StringFromCodePoint(u16);
}
}
return utf8String;
}
static const string SingleUTF8StringFromCodePoint(unsigned int codePoint)
{
string utf8String;
if (codePoint < 0x80) {
utf8String += (unsigned char)codePoint;
}
else if (codePoint < 0x800) {
utf8String += (unsigned char)((codePoint >> 6) | 0xc0);
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
}
else if (codePoint < 0x10000) {
utf8String += (unsigned char)((codePoint >> 12) | 0xe0);
utf8String += (unsigned char)(((codePoint >> 6) & 0x3f) | 0x80);
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
}
else {
utf8String += (unsigned char)((codePoint >> 18) | 0xf0);
utf8String += (unsigned char)((codePoint >> 12) | 0x80);
utf8String += (unsigned char)(((codePoint >> 6) & 0x3f) | 0x80);
utf8String += (unsigned char)((codePoint & 0x3f) | 0x80);
}
return utf8String;
}
static unsigned int CodePointFromSingleUTF8String(const string& utf8String)
{
switch(utf8String.length()) {
case 1:
return (unsigned int)utf8String[0];
case 2:
return (((unsigned char)utf8String[0] << 6) & 0x7ff) + ((unsigned char)utf8String[1] & 0x3f);
case 3:
return (((unsigned char)utf8String[0] << 12) & 0xffff) + (((unsigned char)utf8String[1] << 6) & 0xfff) + ((unsigned char)utf8String[2] & 0x3f);
case 4:
return (((unsigned char)utf8String[0] << 18) & 0x1fffff) + (((unsigned char)utf8String[1] << 12) & 0x3ffff) + (((unsigned char)utf8String[2] << 6) & 0xfff) + ((unsigned char)utf8String[3] & 0x3f);
}
return 0;
}
};
class OVUTF8 {
public:
static const string FromUTF16(const wstring& utf16String)
{
return OVUTF8Helper::StringFromUTF16WideString(utf16String);
}
};
class OVUTF16 {
public:
static const wstring FromUTF8(const string& utf8String)
{
return OVUTF8Helper::ConvertStringToUTF16WideString(utf8String);
}
};
}
#endif

View File

@ -0,0 +1,248 @@
//
// OVWildcard.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OVWildcard_h
#define OVWildcard_h
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
namespace OpenVanilla {
using namespace std;
class OVWildcard {
public:
OVWildcard(const string& expression, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
: m_caseSensitive(caseSensitive)
, m_expression(expression)
, m_matchEndOfLine(matchEndOfLine)
, m_matchOneChar(matchOneChar)
, m_matchZeroOrMoreChar(matchZeroOrMoreChar)
{
size_t index;
for (index = 0; index < expression.length(); index++) {
if (expression[index] == matchOneChar || expression[index] == matchZeroOrMoreChar) break;
}
m_longestHeadMatchString = expression.substr(0, index);
for (string::size_type i = 0; i < expression.length(); i++) {
char c = expression[i];
if (c == matchOneChar) {
m_states.push_back(State(AnyOne, 0));
}
else if (c == matchZeroOrMoreChar) {
char nextChar = 0;
string::size_type j;
for (j = i + 1; j < expression.length(); j++) {
char k = expression[j];
if (k != matchZeroOrMoreChar) {
if (k == matchOneChar) k = -1;
nextChar = k;
break;
}
}
i = j;
m_states.push_back(State(AnyUntil, nextChar));
}
else {
m_states.push_back(State(Exact, c));
}
}
}
bool match(const string& target, size_t fromState = 0) const
{
string::size_type i = 0, slength = target.length();
vector<State>::size_type j, vlength = m_states.size();
for (j = fromState; j < vlength; j++) {
State state = m_states[j];
Directive d = state.first;
int k = state.second;
if (i >= slength) {
if (d == AnyUntil && !k) return true;
return false;
}
switch (d) {
case Exact:
if (!equalChars(target[i], k)) return false;
i++;
break;
case AnyOne:
i++;
break;
case AnyUntil:
if (k == -1) {
// means *?, equals ?, so just advance one character
i++;
}
else if (k == 0) {
// until end, always true
return true;
}
else {
bool found = false;
string::size_type backIndex;
for (backIndex = slength - 1; backIndex >= i; backIndex--) {
if (equalChars(target[backIndex], k)) {
string substring = target.substr(backIndex + 1, slength - (backIndex + 1));
if (match(substring, j + 1)) {
found = true;
i = backIndex + 1;
break;
}
}
if (!backIndex)
break;
}
if (!found)
return false;
}
break;
}
}
if (m_matchEndOfLine && i != slength)
return false;
return true;
}
const string longestHeadMatchString() const
{
return m_longestHeadMatchString;
}
const string expression() const
{
return m_expression;
}
bool isCaseSensitive() const
{
return m_caseSensitive;
}
char matchOneChar() const
{
return m_matchOneChar;
}
char matchZeroOrMoreChar() const
{
return m_matchZeroOrMoreChar;
}
friend ostream& operator<<(ostream& stream, const OVWildcard& wildcard);
protected:
enum Directive {
Exact,
AnyOne,
AnyUntil
};
typedef pair<Directive, int> State;
bool equalChars(char a, char b) const
{
if (m_caseSensitive)
return a == b;
else
return tolower(a) == tolower(b);
}
bool m_caseSensitive;
bool m_matchEndOfLine;
char m_matchOneChar;
char m_matchZeroOrMoreChar;
vector<State> m_states;
string m_expression;
string m_longestHeadMatchString;
public:
static const bool Match(const string& text, const string& expression, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
{
OVWildcard exp(expression, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive);
return exp.match(text);
}
static const vector<OVWildcard> WildcardsFromStrings(const vector<string>& expressions, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
{
vector<OVWildcard> result;
vector<string>::const_iterator iter = expressions.begin();
for ( ; iter != expressions.end(); iter++)
result.push_back(OVWildcard(*iter, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive));
return result;
}
static bool MultiWildcardMatchAny(const string& target, const vector<string>& expressions, char matchOneChar = '?', char matchZeroOrMoreChar = '*', bool matchEndOfLine = true, bool caseSensitive = false)
{
return MultiWildcardMatchAny(target, WildcardsFromStrings(expressions, matchOneChar, matchZeroOrMoreChar, matchEndOfLine, caseSensitive));
}
static bool MultiWildcardMatchAny(const string& target, const vector<OVWildcard>& expressions)
{
vector<OVWildcard>::const_iterator iter = expressions.begin();
for ( ; iter != expressions.end(); iter++) {
if ((*iter).match(target))
return true;
}
return false;
}
};
inline ostream& operator<<(ostream& stream, const OVWildcard& wildcard)
{
vector<OVWildcard::State>::size_type i, size = wildcard.m_states.size();
for (i = 0; i < size; i++) {
const OVWildcard::State& state = wildcard.m_states[i];
stream << "State " << i << ": " << state.first << ", " << state.second << endl;
}
return stream;
}
}
#endif

View File

@ -0,0 +1,97 @@
//
// OpenVanilla.h
//
// Copyright (c) 2007-2010 Lukhnos D. Liu
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#ifndef OpenVanilla_h
#define OpenVanilla_h
#if defined(__APPLE__)
#include <OpenVanilla/OVAroundFilter.h>
#include <OpenVanilla/OVBase.h>
#include <OpenVanilla/OVBenchmark.h>
#include <OpenVanilla/OVCandidateService.h>
#include <OpenVanilla/OVCINDataTable.h>
#include <OpenVanilla/OVCINDatabaseService.h>
#include <OpenVanilla/OVDatabaseService.h>
#include <OpenVanilla/OVDateTimeHelper.h>
#include <OpenVanilla/OVEventHandlingContext.h>
#include <OpenVanilla/OVFileHelper.h>
#include <OpenVanilla/OVFrameworkInfo.h>
#include <OpenVanilla/OVInputMethod.h>
#include <OpenVanilla/OVLocalization.h>
#include <OpenVanilla/OVKey.h>
#include <OpenVanilla/OVKeyValueMap.h>
#include <OpenVanilla/OVLoaderService.h>
#include <OpenVanilla/OVModule.h>
#include <OpenVanilla/OVModulePackage.h>
#include <OpenVanilla/OVOutputFilter.h>
#include <OpenVanilla/OVPathInfo.h>
#include <OpenVanilla/OVStringHelper.h>
#include <OpenVanilla/OVTextBuffer.h>
#include <OpenVanilla/OVUTF8Helper.h>
#include <OpenVanilla/OVWildcard.h>
#ifdef OV_USE_SQLITE
#include <OpenVanilla/OVSQLiteDatabaseService.h>
#include <OpenVanilla/OVSQLiteWrapper.h>
#endif
#else
#ifdef WIN32
#include <windows.h>
#endif
#include "OVAroundFilter.h"
#include "OVBase.h"
#include "OVBenchmark.h"
#include "OVCandidateService.h"
#include "OVCINDataTable.h"
#include "OVCINDatabaseService.h"
#include "OVDatabaseService.h"
#include "OVDateTimeHelper.h"
#include "OVEventHandlingContext.h"
#include "OVFileHelper.h"
#include "OVFrameworkInfo.h"
#include "OVInputMethod.h"
#include "OVLocalization.h"
#include "OVKey.h"
#include "OVKeyValueMap.h"
#include "OVLoaderService.h"
#include "OVModule.h"
#include "OVModulePackage.h"
#include "OVOutputFilter.h"
#include "OVPathInfo.h"
#include "OVStringHelper.h"
#include "OVTextBuffer.h"
#include "OVUTF8Helper.h"
#include "OVWildcard.h"
#ifdef OV_USE_SQLITE
#include "OVSQLiteDatabaseService.h"
#include "OVSQLiteWrapper.h"
#endif
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More