mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Robin Clark's original xacc-0.9 source
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
97d79a0468
commit
1668431953
96
CHANGES
Normal file
96
CHANGES
Normal file
@ -0,0 +1,96 @@
|
||||
Version history:
|
||||
------- -------
|
||||
0.9 - 08 Sep 97
|
||||
o Lots of code-cleanup.
|
||||
o Adjust Balance window.
|
||||
o Reconcile window! Makes it easy to reconcile your account
|
||||
at the end of the month when you get your new bank statement.
|
||||
o Hypertext, context sensitive help. A pretty nice add-on,
|
||||
thanks to libhtmlw, from NCSA Mosaic. (Now someone just
|
||||
has to write some decent help pages!)
|
||||
o Fixed busy cursor. Previously the code the switched cursors
|
||||
caused the program to crash, so it wasn't enabled. Now it
|
||||
works, and is enabled.
|
||||
|
||||
0.7 - 14 Jul 97
|
||||
o Started adding support for account types other than "BANK".
|
||||
Still no support for Portfolio and Mutual accounts. (They
|
||||
are greyed out in the "New Account" window for now.)
|
||||
o Changed the balance field to use red/black text to denote
|
||||
negative/positive balance (instead of using a sign... If you
|
||||
define USE_NO_COLOR when compiling, it will revert to the
|
||||
old method of displaying a '-' in front of negative balances)
|
||||
o Fixed bug in automatic transfers that cause the "From"
|
||||
account to always be the first account, and the "To" account
|
||||
to possibly be incorrect. Also, added "[To: ]" "[From: ]"
|
||||
(with to account name, and from account name) to the start
|
||||
of the memo field, so you can keep track of where the money
|
||||
comes from/goes to.
|
||||
|
||||
0.6 - 28 Jun 97
|
||||
o Fixed balance/reconciled field (in bottom right corner
|
||||
of register window. (It sorta works now, with lesstif.
|
||||
I don't know about motif... you have to leave the current
|
||||
transaction for the balances to be recalculated.)
|
||||
o Rearranged directory structure... the source was growing
|
||||
to too many files to have it all in one directory.
|
||||
|
||||
0.5 - 6 Jun 97 Mostly, minor bug fixes
|
||||
o verifyDate -- affects when accelerator keys in the
|
||||
register window cause the date to cross a year boundary
|
||||
o Fixed handling of the date in the transfer window. Before
|
||||
if the user pressed the "transfer" button with an incomplete
|
||||
date in the date field, the resulting date would be
|
||||
undefined.
|
||||
o If the user doesn't enter data in the description field,
|
||||
The number field, the memo field, or one of the amount
|
||||
fields, the the new transaction isn't added when the
|
||||
user leaves the new transaction, or presses "Record"
|
||||
o Now user is prevented from entering more than one '.'
|
||||
in the amount fields in the register and transfer windows.
|
||||
Also, the user is prevented from entering more than two
|
||||
'/' in the date field in the transfer window.
|
||||
o Fixed a (very small) memory leak in the transfer window.
|
||||
o Fixed a bug in the transfer window that resulted in a
|
||||
different amount subtracted from the "from" account as was
|
||||
added to the "to" account.
|
||||
o Fixed bug that caused a segfault when deleting the last
|
||||
transaction in the register window.
|
||||
o Now if the user is in the last transaction (the empty
|
||||
transaction) in the register window, the "Delete" button
|
||||
does not do anything.
|
||||
|
||||
0.4 - 3 Jun 97
|
||||
o Added "Balance" and "Reconciled" balance to the bottom
|
||||
right corner of the register window.
|
||||
o The main window uses an Xbae-Matrix widget now, instead
|
||||
of a list, in order to line up the account names, types,
|
||||
and balances in nice columns.
|
||||
|
||||
0.2 - First (mostly) functional release. Most of the buttons,
|
||||
and menu bar choices actually do something now.
|
||||
|
||||
0.1 - First demo release. Lots of buttons, and menu bar choices
|
||||
Don't do anything. The register window is still pretty
|
||||
buggy.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Things to do/fix: (in no particular order)
|
||||
------ -- ------
|
||||
|
||||
o Reg window segfaults on close... (I think this might be a
|
||||
lesstif problem, so try a newer version)
|
||||
|
||||
o memorized transactions/quickfill (They work, but you need
|
||||
a newer than v4.6.1 Xbae Widget)
|
||||
|
||||
o Bug Fixes! There are still a few bugs floating around.
|
||||
(Let me know if you find any)
|
||||
|
||||
o a README and/or man page!
|
||||
|
||||
o use configure or Imake? or at least a proper "make install"
|
||||
|
339
COPYING
Normal file
339
COPYING
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, 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
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
155
Docs/pix.xpm
Normal file
155
Docs/pix.xpm
Normal file
@ -0,0 +1,155 @@
|
||||
/* XPM */
|
||||
static char * EscherCube_xpm[] = {
|
||||
"48 48 104 2",
|
||||
" c None",
|
||||
". c #30C230C22081",
|
||||
"X c #30C230C230C2",
|
||||
"o c #30C2410330C2",
|
||||
"O c #410330C24103",
|
||||
"+ c #410341034103",
|
||||
"@ c #514451445144",
|
||||
"# c #514461855144",
|
||||
"$ c #618551446185",
|
||||
"% c #618561856185",
|
||||
"& c #71C671C671C6",
|
||||
"* c #71C6820771C6",
|
||||
"= c #965882078617",
|
||||
"- c #861792488617",
|
||||
"; c #965892489658",
|
||||
": c #9658A2899658",
|
||||
"> c #9E79A2899E79",
|
||||
", c #AEBAAEBA9E79",
|
||||
"< c #AEBAAEBAAEBA",
|
||||
"1 c #AEBABEFBAEBA",
|
||||
"2 c #BEFBBEFBBEFB",
|
||||
"3 c #CF3CBEFBCF3C",
|
||||
"4 c #CF3CCF3CCF3C",
|
||||
"5 c #DF7DCF3CCF3C",
|
||||
"6 c #DF7DDF7DCF3C",
|
||||
"7 c #DF7DDF7DDF7D",
|
||||
"8 c #EFBEDF7DDF7D",
|
||||
"9 c #DF7DEFBEDF7D",
|
||||
"0 c #EFBEDF7DEFBE",
|
||||
"q c #EFBEEFBEDF7D",
|
||||
"w c #208130C22081",
|
||||
"e c #410351445144",
|
||||
"r c #514451446185",
|
||||
"t c #71C6618571C6",
|
||||
"y c #861771C68617",
|
||||
"u c #9E7992489E79",
|
||||
"i c #9E79AEBA9E79",
|
||||
"p c #BEFBAEBABEFB",
|
||||
"a c #BEFBCF3CBEFB",
|
||||
"s c #BEFBCF3CCF3C",
|
||||
"d c #CF3CCF3CDF7D",
|
||||
"f c #CF3CDF7DCF3C",
|
||||
"g c #DF7DDF7DEFBE",
|
||||
"h c #208120812081",
|
||||
"j c #30C2208130C2",
|
||||
"k c #410330C230C2",
|
||||
"l c #4103410330C2",
|
||||
"z c #410351444103",
|
||||
"x c #618551445144",
|
||||
"c c #618561855144",
|
||||
"v c #618571C66185",
|
||||
"b c #861771C671C6",
|
||||
"n c #8617820771C6",
|
||||
"m c #965882079658",
|
||||
"M c #9E7992489658",
|
||||
"N c #AEBAA289AEBA",
|
||||
"B c #BEFBAEBAAEBA",
|
||||
"V c #DF7DCF3CDF7D",
|
||||
"C c #CF3CDF7DDF7D",
|
||||
"Z c #208120811040",
|
||||
"A c #965892488617",
|
||||
"S c #104020812081",
|
||||
"D c #861782078617",
|
||||
"F c #861792489658",
|
||||
"G c #965892489E79",
|
||||
"H c #104020811040",
|
||||
"J c #208110402081",
|
||||
"K c #30C220812081",
|
||||
"L c #BEFBBEFBCF3C",
|
||||
"P c #104010401040",
|
||||
"I c #208110401040",
|
||||
"U c #618571C671C6",
|
||||
"Y c #71C671C68617",
|
||||
"T c #71C682078617",
|
||||
"R c #CF3CBEFBBEFB",
|
||||
"E c #CF3CCF3CBEFB",
|
||||
"W c #000010401040",
|
||||
"Q c #104010402081",
|
||||
"! c #9E79AEBAAEBA",
|
||||
"~ c #104010400000",
|
||||
"^ c #AEBAA2899E79",
|
||||
"/ c #71C671C66185",
|
||||
"( c #000010400000",
|
||||
") c #000000000000",
|
||||
"_ c #104000001040",
|
||||
"` c #2081208130C2",
|
||||
"' c #9658A2899E79",
|
||||
"] c #104000000000",
|
||||
"[ c #000000001040",
|
||||
"{ c #30C241034103",
|
||||
"} c #9E79A289AEBA",
|
||||
"| c #AEBABEFBBEFB",
|
||||
" . c #514461856185",
|
||||
".. c #9E79A2899658",
|
||||
"X. c #71C661856185",
|
||||
"o. c #30C230C24103",
|
||||
"O. c #514441035144",
|
||||
"+. c #514451444103",
|
||||
"@. c #410341035144",
|
||||
"#. c #AEBAAEBABEFB",
|
||||
"$. c #208130C230C2",
|
||||
"%. c #6185618571C6",
|
||||
"&. c #514441034103",
|
||||
"*. c #861782079658",
|
||||
" . X o O + @ # $ % & * = - ; : > , < 1 2 2 3 4 5 6 7 7 8 9 0 q ",
|
||||
" w X X O + @ e r % t & y - ; : u i < < p a 3 s d f 7 7 g 9 0 9 ; ",
|
||||
" h j X k l + z x c t v b n m ; M > N < B 2 2 a 3 4 V 6 7 7 0 9 m ; ",
|
||||
" h h w X f d f d f V f V f 7 f 7 C 7 f V f V f d f V f 7 9 g 9 m ; ; ",
|
||||
" Z h w j - 4 4 5 4 5 4 5 4 V f V 6 V f V f V 4 5 4 5 4 V 7 7 7 m A ; ; ",
|
||||
" S h h j - D s 4 4 4 4 4 4 4 4 d f V f d f d 4 d 4 4 4 V C 7 7 m - ; F G ",
|
||||
" H J Z K * D D m ; M 5 4 V 7 = D m - ; ; ",
|
||||
" H h S h * y D L F ; : 4 f V C D D m a ; ; G ",
|
||||
" P I H J & b n 2 2 m A M 3 4 5 f y D = 2 2 A ; ; ",
|
||||
" P P H J U Y & p 1 2 - ; : 4 4 d f y T D 1 p 1 ; F G ",
|
||||
" P P H J % t & < < < m ; u R E 4 f b * y B < < A ; ; ",
|
||||
" W P P Q % t v < ! < - ; : L a 4 4 & * y < < ! ; ; G ",
|
||||
" ~ P ~ I c $ % > ^ > m ; M 2 2 3 4 t / b ^ i ^ ; M ; ",
|
||||
" ( P W P # $ % > > > F ; : p a 3 s t U & > > > ; ; G ",
|
||||
" ) _ ( _ @ $ # M ; u m ; u p 2 2 a % v t M ; u ; M ; ",
|
||||
" ( _ ( P P P H h h ` w X o : ; F F ; : & * D - G ' > i < 1 2 a % v t : ; F ; : u ",
|
||||
" ) ] ( _ ~ P P I Z h w j X O m - m ; ; M & y - m ; > i N < 2 2 $ c % m - m ; M : ",
|
||||
") [ ( _ W P P Q H h h j X O { D D - F G : y T m ; u > } < p | r .% D D - G : u ",
|
||||
"V f 5 4 5 f V f V f V f V f V y * y m ; u f 5 f V f 5 4 V f x @ $ y * y : u ..",
|
||||
"4 d f 4 f d f d 4 d f V f V f U & U F G : d f d f d f 4 4 d @ r # U & U G : > ",
|
||||
"3 4 3 E 4 E 4 4 3 4 4 4 5 4 5 t v X.; ; u 4 4 4 4 E 4 E 3 4 @ @ x t v X.; u ..",
|
||||
"a 4 a o.{ + .% v ; G > 3 a 4 e @ # .% v u ' > ",
|
||||
"3 2 3 X O o $ # $ ; ; u 2 3 2 O.+.@ $ # $ : u > ",
|
||||
"a 2 a X o + @ @ @ ; u ' 2 2 2 z @ @ @ @ @ u > } ",
|
||||
"p < p X k l O.z O.; : u 1 p < O.+.@ O.z O...> i ",
|
||||
"1 < 1 o.o + @.z @.; G > #.1 < z O.@ + @.z > > } ",
|
||||
"N , N X O o l + o ; ; u 1 1 1 O.+.@ O l + : u > ",
|
||||
"i } i o.o + O o o.; u o + z @ # % v } i } e @ @ } < #.| L a 4 f V o o.o G ' > ",
|
||||
"> ..u o O + . X . ; o O + O.@ $ % & u u ..@ @ x , < 1 2 2 3 4 5 6 X . X ; u ..",
|
||||
"' u : O + + j $.j $.o.{ O.e r % %.U G : u @ r # < < p 2 3 s d f 7 $.j $.u : u ",
|
||||
"; A M l + + h j . K h j h K h h h h ; ; A x @ $ h h h h h K h j 6 7 7 0 : u ..",
|
||||
"- m - + { @. h h w %.w h h h h h S h S m - m # r # h S h S h h h f 7 9 g F G : ",
|
||||
"y D D l + + Z h h t % h Z J Z J Z J Z J D y D x # $ H J Z J Z J f V 7 7 - M ; ",
|
||||
"* y * + z O. S h h & U t y * y @ $ . 4 d C 7 - m ; ",
|
||||
"& / b l + + P J Z y & t & & / x c $ E 5 4 V n = D ",
|
||||
"v %.v + z O. H J H D * & & v %.# % . a 4 f V * D - ",
|
||||
"X.% % + &.z P P H D n y c $ % $ c $ a 3 4 V * y D ",
|
||||
"# $ # + z @ P P H J m - D $ # $ # $ % 2 3 4 d * y T ",
|
||||
"@ @ x + + z W P P Q m D m @ @ @ $ c % 2 R E 4 & b * ",
|
||||
"z O.e + z @ P ~ I ; ; *. @ z O. .% % L s 4 U & * ",
|
||||
"&.+ &.l &.+.W P M ; m + &.+ $ c X.2 3 v t & ",
|
||||
"{ + { @.z O._ u ' ; + { + .$ % 3 v t & ",
|
||||
"O o k + O.P P P H h h ` w X o l + z @ c X./ b n m ; u o O o $ % % % t v ",
|
||||
"$.X $.@._ ~ P P I Z h w j X O + + @ # % v & * D - ; : X $.X .% v %.v ",
|
||||
"j . j _ W P P Q H h h j X O { + &.@ $ c t & y D m ; > . j . % c X.% ",
|
||||
"w j w ` w j w ` w ` h ` h h S h h h h ` h ` w ` w j w ` w j .% % ",
|
||||
"h h K h h h h h h h J h J H J Z J H J h h h h h h h J h h h $ % ",
|
||||
"S h h h H h S h S h S h H Q H J H Q H h H h S h S h S h S h . "};
|
38
Docs/xacc-about.html
Normal file
38
Docs/xacc-about.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>About X-Accountant</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor=#eeeeee>
|
||||
<h1>About X-Accountant</h1>
|
||||
|
||||
<hr>
|
||||
|
||||
X-Accountant is a program to keep track of your finances. Some
|
||||
of the features are:
|
||||
|
||||
<ul>
|
||||
<li> Multiple accounts, which can be open at
|
||||
the same time. Create one xacc account
|
||||
for each of your bank accounts.
|
||||
<li> Each account keeps a running balance and
|
||||
a reconciled balance, so you can keep track
|
||||
of the checks that have clear your account.
|
||||
<li> A simple interface. If you can use the
|
||||
register in the back of your checkbook,
|
||||
you can use xacc.
|
||||
<li> Automatic account reconciling. At the end
|
||||
of the month, open up the reconcile window,
|
||||
enter your bank statement's ending balance,
|
||||
and check off the transactions that appear
|
||||
in the bank statement. This makes it easy
|
||||
to track down any discrepancies.
|
||||
<li> QuickFill... if you begin typing a description
|
||||
in the description fields, and it matches an
|
||||
previous transaction, hitting TAB will copy
|
||||
the previous transaction. Handy if you have
|
||||
similar transactions on a regular basis.
|
||||
|
||||
</body>
|
||||
</html>
|
330
Docs/xacc-gpl.html
Normal file
330
Docs/xacc-gpl.html
Normal file
@ -0,0 +1,330 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>GNU General Public License</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor=#eeeeee>
|
||||
<h1>GNU General Public License</h1>
|
||||
<h2>Version 2, June 1991</h2>
|
||||
|
||||
<CENTER>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA<P>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.<P>
|
||||
</CENTER>
|
||||
<P>
|
||||
<h3><a name="SEC001">Preamble</a></h3>
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
<HR>
|
||||
<h3>GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</h3>
|
||||
|
||||
<P>
|
||||
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".
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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:
|
||||
|
||||
<blockquote>
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
<P>
|
||||
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.
|
||||
<P>
|
||||
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.)
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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:
|
||||
|
||||
<blockquote>
|
||||
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,
|
||||
<P>
|
||||
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,
|
||||
<P>
|
||||
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.)
|
||||
</blockquote>
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<HR>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<HR>
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
<P>
|
||||
|
||||
<h3>NO WARRANTY</h3>
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<P>
|
||||
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.
|
||||
|
||||
<h3>END OF TERMS AND CONDITIONS</h3>
|
||||
|
||||
<hr>
|
||||
</body>
|
||||
</html>
|
16
Docs/xacc-main.html
Normal file
16
Docs/xacc-main.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Help</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
For help on a specific topic:
|
||||
<ul>
|
||||
<li><a href="xacc-gpl.html" name="SEC001">Creating a new account</a>
|
||||
<li><a href="xacc-gpl.html">Creating a new account</a>
|
||||
<li><a href="xacc-about.html">Creating a new account</a>
|
||||
<hr>
|
||||
|
||||
</body>
|
||||
</html>
|
13
Docs/xacc-recnwin.html
Normal file
13
Docs/xacc-recnwin.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1></h1>
|
||||
|
||||
<hr>
|
||||
|
||||
</body>
|
||||
</html>
|
13
Docs/xacc-regwin.html
Normal file
13
Docs/xacc-regwin.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1></h1>
|
||||
|
||||
<hr>
|
||||
|
||||
</body>
|
||||
</html>
|
73
Makefile
Normal file
73
Makefile
Normal file
@ -0,0 +1,73 @@
|
||||
######################################################################
|
||||
#********************************************************************
|
||||
#* Makefile -- makefile for xacc (X-Accountant) *
|
||||
#* Copyright (C) 1997 Robin D. Clark *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or *
|
||||
#* modify it under the terms of the GNU General Public License as *
|
||||
#* published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU General Public License*
|
||||
#* along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
#* *
|
||||
#* Author: Rob Clark *
|
||||
#* Internet: rclark@cs.hmc.edu *
|
||||
#* Address: 609 8th Street *
|
||||
#* Huntington Beach, CA 92648-4632 *
|
||||
#********************************************************************
|
||||
|
||||
|
||||
######################################################################
|
||||
# CONFIGURABLE STUFF: #
|
||||
CC = gcc
|
||||
AR = ar r
|
||||
RANLIB = ranlib
|
||||
|
||||
# USE_NO_COLOR - don't use red/black colors to denote neg/positive
|
||||
# balances, but instead display a signed number in
|
||||
# the balance field
|
||||
# USEQUICKFILL - comment out if you get a compile error about
|
||||
# XbaeMatrixSetCursorPosition
|
||||
# HYPER_HELP - include hyper-text help system
|
||||
# DEBUGMEMORY - does some accounting whenever malloc/free
|
||||
# is called.
|
||||
# USEDEBUG - causes debugging info to be displayed
|
||||
CFLAGS = $(LFLAGS) -I../include -I../libhtmlw -I/usr/X11/include \
|
||||
-I/usr/local/include -DMOTIF1_2 \
|
||||
-DUSEQUICKFILL # -DUSE_NO_COLOR -DDEBUGMEMORY -DUSEDEBUG
|
||||
LFLAGS = -g -L/usr/local/lib -L/usr/X11/lib
|
||||
LIBS = -lXm -lXmu -lXbae -lXt -lXext -lX11 -lSM -lICE -lXpm
|
||||
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# DO NOT EDIT THE STUFF BELOW THIS LINE! #
|
||||
|
||||
OPTIONS = "CC = $(CC)" "LFLAGS = $(LFLAGS)" \
|
||||
"CFLAGS = $(CFLAGS)" "LIBS = $(LIBS)" \
|
||||
"RANLIB = $(RANLIB)" "AR = $(AR)"
|
||||
|
||||
default :
|
||||
@cd libhtmlw ; $(MAKE) $(OPTIONS)
|
||||
@cd src ; $(MAKE) $(OPTIONS)
|
||||
|
||||
clean :
|
||||
rm -f *~ *.bak
|
||||
@cd include ; rm -f *~
|
||||
@cd help ; rm -f *~
|
||||
@cd libhtmlw ; $(MAKE) clean
|
||||
@cd src ; $(MAKE) clean
|
||||
|
||||
really_clean : clean
|
||||
@cd src ; $(MAKE) really_clean
|
||||
|
||||
depend :
|
||||
@cd src ; $(MAKE) depend $(OPTIONS)
|
||||
|
38
README
Normal file
38
README
Normal file
@ -0,0 +1,38 @@
|
||||
X-Accountant
|
||||
------------
|
||||
|
||||
xacc is a program to keep track of your finances. It is similar in
|
||||
concept to Quicken(TM). Although xacc still lacks the advanced
|
||||
features of quicken, it does have the basic functionality. Some
|
||||
of the features of xacc are:
|
||||
|
||||
- Multiple Accounts
|
||||
- Each account keeps a running balance and
|
||||
a reconciled balance, so you can keep track
|
||||
of the checks that have clear your account.
|
||||
- A simple interface. If you can use the
|
||||
register in the back of your checkbook,
|
||||
you can use xacc.
|
||||
- QuickFill... if you begin typing a description
|
||||
in the description fields, and it matches an
|
||||
previous transaction, hitting <TAB> will copy
|
||||
the previous transaction. Handy if you have
|
||||
similar transactions on a regular basis.
|
||||
(such as depositing your paycheck every week :)
|
||||
|
||||
To install:
|
||||
-----------
|
||||
|
||||
First check the makefile to ensure that all the paths are ok.
|
||||
Also, make sure that the Xbae-Matrix widget and Motif or
|
||||
Lesstif are installed. You can get Lesstif from
|
||||
http://www.lesstif.org. You can get The Xbae widget from
|
||||
ftp://ftp.x.org/contrib/widgets/motif/ or any mirror. If
|
||||
you are using a version of Xbae 4.6.1, you will need to
|
||||
comment out "-DUSEQUICKFILL" in the Makefile.
|
||||
|
||||
# make depend
|
||||
# make
|
||||
|
||||
sorry, no "make install" yet.
|
||||
|
672
src/AccWindow.c
Normal file
672
src/AccWindow.c
Normal file
@ -0,0 +1,672 @@
|
||||
/********************************************************************\
|
||||
* AccWindow.c -- window for creating new accounts for xacc *
|
||||
* (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
#include <Xm/ToggleB.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Account.h"
|
||||
#include "Data.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
/* NOTE: notes has to be at the beginning of the struct! Order is
|
||||
* important */
|
||||
typedef struct _accwindow {
|
||||
String notes; /* The text from the "Notes" window */
|
||||
/* The account type buttons: */
|
||||
Widget bank;
|
||||
Widget cash;
|
||||
Widget asset;
|
||||
Widget credit;
|
||||
Widget liability;
|
||||
Widget portfolio;
|
||||
Widget mutual;
|
||||
/* The text fields: */
|
||||
Widget name; /* The account name text field */
|
||||
Widget desc; /* Account description text field */
|
||||
} AccWindow;
|
||||
|
||||
/* NOTE: notes has to be at the beginning of the struct! Order is
|
||||
* important */
|
||||
typedef struct _editaccwindow {
|
||||
String notes; /* The text from the "Notes" window */
|
||||
/* The text fields: */
|
||||
Widget name; /* The account name text field */
|
||||
Widget desc; /* Account description text field */
|
||||
|
||||
Account *account; /* The text from the "Notes" window */
|
||||
} EditAccWindow;
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Data *data;
|
||||
extern Widget toplevel;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void closeAccWindow( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void closeEditAccWindow( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void notesCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void createCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void editCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* accWindow *
|
||||
* opens up a window to create a new account... the account is *
|
||||
* actually created in the "create" callback *
|
||||
* *
|
||||
* Args: parent - the parent of the window to be created *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
accWindow( Widget parent )
|
||||
{
|
||||
Widget dialog, form, frame, rc, widget,
|
||||
label, buttonform;
|
||||
AccWindow *accData;
|
||||
int position;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
accData = (AccWindow *)_malloc(sizeof(AccWindow));
|
||||
accData->notes = XtNewString("");
|
||||
|
||||
/* force the size of the dialog so it is not resizable */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNtitle, "Set Up Account",
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNwidth, 350,
|
||||
XmNminWidth, 350,
|
||||
XmNmaxWidth, 350,
|
||||
XmNheight, 300,
|
||||
XmNminHeight, 300,
|
||||
XmNmaxHeight, 300,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( dialog, XmNdestroyCallback,
|
||||
closeAccWindow, (XtPointer)accData );
|
||||
|
||||
/* The form to put everything in the dialog in */
|
||||
form = XtVaCreateWidget( "form", xmFormWidgetClass, dialog, NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The account type area *
|
||||
\******************************************************************/
|
||||
|
||||
/* Label tells the user what this area is */
|
||||
widget = XtVaCreateManagedWidget( "Account Type",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
NULL );
|
||||
|
||||
/* Makes a nice looking frame around the radio buttons */
|
||||
frame = XtVaCreateManagedWidget( "frame",
|
||||
xmFrameWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, widget,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 20,
|
||||
NULL);
|
||||
|
||||
/* A RowCol goes in the frame, to place the buttons */
|
||||
rc = XtVaCreateManagedWidget( "rowcol",
|
||||
xmRowColumnWidgetClass, frame,
|
||||
/*XmNentryAlignment, XmALIGNMENT_CENTER,*/
|
||||
XmNorientation, XmVERTICAL,
|
||||
XmNmarginHeight, 10,
|
||||
XmNmarginWidth, 10,
|
||||
/*XmNpacking, XmPACK_TIGHT,*/
|
||||
XmNradioBehavior, True,
|
||||
XmNnumColumns, 2,
|
||||
NULL );
|
||||
|
||||
/* Create the buttons */
|
||||
accData->bank =
|
||||
XtVaCreateManagedWidget( "Bank",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
XmNset, True,
|
||||
NULL);
|
||||
|
||||
accData->cash =
|
||||
XtVaCreateManagedWidget( "Cash",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
|
||||
accData->asset =
|
||||
XtVaCreateManagedWidget( "Asset",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
|
||||
accData->credit =
|
||||
XtVaCreateManagedWidget( "Credit Card",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
|
||||
accData->liability =
|
||||
XtVaCreateManagedWidget( "Liability",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
|
||||
accData->portfolio =
|
||||
XtVaCreateManagedWidget( "Portfolio",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
/* Portfolio account not supported yet, so grey it out: */
|
||||
XtSetSensitive( accData->portfolio, False );
|
||||
|
||||
accData->mutual =
|
||||
XtVaCreateManagedWidget( "Mutual Fund",
|
||||
xmToggleButtonWidgetClass, rc,
|
||||
XmNindicatorType, XmONE_OF_MANY,
|
||||
NULL);
|
||||
/* Mutual Fund account not supported yet, so grey it out: */
|
||||
XtSetSensitive( accData->mutual, False );
|
||||
|
||||
/******************************************************************\
|
||||
* Text fields.... *
|
||||
\******************************************************************/
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Account Name:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
accData->name =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNmaxLength, 40,
|
||||
XmNcolumns, 25,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Description:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, accData->name,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
accData->desc =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNmaxLength, 40,
|
||||
XmNcolumns, 30,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, accData->name,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The buttons at the bottom... *
|
||||
\******************************************************************/
|
||||
|
||||
buttonform = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, form,
|
||||
XmNfractionBase, 5,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, accData->desc,
|
||||
XmNtopOffset, 10,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNbottomOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
position = 1; /* puts the buttons in the right place */
|
||||
|
||||
/* The "Notes" button opens a window to a few lines of notes about
|
||||
* the account */
|
||||
widget = XtVaCreateManagedWidget( "Notes",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
notesCB, (XtPointer)accData );
|
||||
|
||||
/* The "Cancel" button */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
/* We need to do something to clean up memory too! */
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
/* The "Create" button creates the new account with the data
|
||||
* that the user entered */
|
||||
widget = XtVaCreateManagedWidget( "Create",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
createCB, (XtPointer)accData );
|
||||
/* We need to do something to clean up memory too! */
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
XtManageChild(buttonform);
|
||||
|
||||
/******************************************************************/
|
||||
XtManageChild(form);
|
||||
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* closeAccWindow *
|
||||
* frees memory allocated for an accWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - accData - the struct for the accWindow that is *
|
||||
* being closed *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
closeAccWindow( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
AccWindow *accData = (AccWindow *)cd;
|
||||
|
||||
_free(accData);
|
||||
DEBUG("close AccWindow");
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* editAccWindow *
|
||||
* opens up a window to edit an account *
|
||||
* *
|
||||
* Args: parent - the parent of the window to be created *
|
||||
* account - the account to edit *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
editAccWindow( Widget parent, Account *account )
|
||||
{
|
||||
Widget dialog, form, widget, label, buttonform;
|
||||
EditAccWindow *editAccData;
|
||||
int position;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
editAccData = (EditAccWindow *)_malloc(sizeof(EditAccWindow));
|
||||
editAccData->notes = account->notes;
|
||||
editAccData->account = account;
|
||||
|
||||
/* force the size of the dialog so it is not resizable */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNtitle, "Edit Account",
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNwidth, 350,
|
||||
XmNminWidth, 350,
|
||||
XmNmaxWidth, 350,
|
||||
XmNheight, 150,
|
||||
XmNminHeight, 150,
|
||||
XmNmaxHeight, 150,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( dialog, XmNdestroyCallback,
|
||||
closeEditAccWindow, (XtPointer)editAccData );
|
||||
|
||||
/* The form to put everything in the dialog in */
|
||||
form = XtVaCreateWidget( "form", xmFormWidgetClass, dialog, NULL );
|
||||
/******************************************************************\
|
||||
* Text fields.... *
|
||||
\******************************************************************/
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Account Name:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
editAccData->name =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNmaxLength, 40,
|
||||
XmNcolumns, 25,
|
||||
XmNvalue, account->accountName,
|
||||
XmNeditable, True,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Description:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, editAccData->name,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
editAccData->desc =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNmaxLength, 40,
|
||||
XmNcolumns, 30,
|
||||
XmNvalue, account->description,
|
||||
XmNeditable, True,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, editAccData->name,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 35, /* 35% */
|
||||
NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The buttons at the bottom... *
|
||||
\******************************************************************/
|
||||
|
||||
buttonform =
|
||||
XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, form,
|
||||
XmNfractionBase, 5,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, editAccData->desc,
|
||||
XmNtopOffset, 10,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNbottomOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
position = 1; /* puts the buttons in the right place */
|
||||
|
||||
/* The "Notes" button opens a window to a few lines of notes about
|
||||
* the account */
|
||||
widget =
|
||||
XtVaCreateManagedWidget( "Notes",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
notesCB, (XtPointer)editAccData );
|
||||
|
||||
/* The "Cancel" button */
|
||||
widget =
|
||||
XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
/* We need to do something to clean up memory too! */
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
/* The "Create" button creates the new account with the data
|
||||
* that the user entered */
|
||||
widget =
|
||||
XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
editCB, (XtPointer)editAccData );
|
||||
/* We need to do something to clean up memory too! */
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
XtManageChild(buttonform);
|
||||
|
||||
/******************************************************************/
|
||||
XtManageChild(form);
|
||||
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* closeEditAccWindow *
|
||||
* frees memory allocated for an editAccWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - editAccData - the struct for the editAccWindow *
|
||||
* that is being closed *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
closeEditAccWindow( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
EditAccWindow *editAccData = (EditAccWindow *)cd;
|
||||
|
||||
_free(editAccData);
|
||||
DEBUG("close EditAccWindow");
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* notesCB -- called when the user presses the "Notes" Button *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - accData - the struct that has the notes text in it *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: toplevel - the toplevel widget *
|
||||
\********************************************************************/
|
||||
void
|
||||
notesCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
AccWindow *accData = (AccWindow *)cd;
|
||||
|
||||
accData->notes = textBox( toplevel, "Notes", accData->notes, True );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* createCB -- creates the new account from data in the newaccount *
|
||||
* dialog window *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - accData - the struct of data associated with this *
|
||||
* accWindow. *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
* toplevel - the toplevel widget *
|
||||
\********************************************************************/
|
||||
void
|
||||
createCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int i,num;
|
||||
Transaction *trans;
|
||||
Account *acc;
|
||||
AccWindow *accData = (AccWindow *)cd;
|
||||
|
||||
String name = XmTextGetString(accData->name);
|
||||
String desc = XmTextGetString(accData->desc);
|
||||
|
||||
/* The account has to have a name! */
|
||||
if( strcmp( name, "" ) == 0 )
|
||||
return;
|
||||
|
||||
acc = mallocAccount();
|
||||
acc->flags = 0;
|
||||
acc->accountName = name;
|
||||
acc->description = desc;
|
||||
acc->notes = accData->notes;
|
||||
|
||||
/* figure out account type */
|
||||
{
|
||||
Boolean set = False;
|
||||
|
||||
XtVaGetValues( accData->bank, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = BANK;
|
||||
|
||||
XtVaGetValues( accData->cash, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = CASH;
|
||||
|
||||
XtVaGetValues( accData->asset, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = ASSET;
|
||||
|
||||
XtVaGetValues( accData->credit, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = CREDIT;
|
||||
|
||||
XtVaGetValues( accData->liability, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = LIABILITY;
|
||||
|
||||
XtVaGetValues( accData->portfolio, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = PORTFOLIO;
|
||||
|
||||
XtVaGetValues( accData->mutual, XmNset, &set, NULL );
|
||||
if(set)
|
||||
acc->type = MUTUAL;
|
||||
}
|
||||
|
||||
/* Add an opening balance transaction (as the first transaction) */
|
||||
trans = (Transaction *)_malloc(sizeof(Transaction));
|
||||
|
||||
todaysDate( &(trans->date) );
|
||||
trans->num = XtNewString("");
|
||||
trans->description = XtNewString("Opening Balance\0");
|
||||
trans->memo = XtNewString("");
|
||||
trans->catagory = 0;
|
||||
trans->reconciled = NREC;
|
||||
trans->amount = 0;
|
||||
|
||||
/* add the new transaction to the account */
|
||||
insertTransaction( acc, trans );
|
||||
|
||||
/* once the account is set up, add it to data */
|
||||
insertAccount( data, acc );
|
||||
|
||||
/* make sure the accountlist is updated to reflect the new account */
|
||||
refreshMainWindow();
|
||||
/* open up the account window for the user */
|
||||
regWindow( toplevel, acc );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* editCB -- records the edits made by in the editAccWindow *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - editAccData - the struct of data associated with *
|
||||
* the EditAccWindow *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
\********************************************************************/
|
||||
void
|
||||
editCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
EditAccWindow *editAccData = (EditAccWindow *)cd;
|
||||
String name = XmTextGetString(editAccData->name);
|
||||
String desc = XmTextGetString(editAccData->desc);
|
||||
|
||||
/* The account has to have a name! */
|
||||
if( strcmp( name, "" ) != 0 )
|
||||
{
|
||||
XtFree(editAccData->account->accountName);
|
||||
editAccData->account->accountName = name;
|
||||
}
|
||||
|
||||
XtFree(editAccData->account->description);
|
||||
editAccData->account->description = name;
|
||||
|
||||
refreshMainWindow();
|
||||
}
|
211
src/Account.c
Normal file
211
src/Account.c
Normal file
@ -0,0 +1,211 @@
|
||||
/********************************************************************\
|
||||
* Account.c -- the Account data structure *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "Data.h"
|
||||
#include "Account.h"
|
||||
#include "date.h"
|
||||
|
||||
extern Data *data;
|
||||
|
||||
/********************************************************************\
|
||||
* Because I can't use C++ for this project, doesn't mean that I *
|
||||
* can't pretend too! These functions perform actions on the *
|
||||
* account data structure, in order to encapsulate the knowledge *
|
||||
* of the internals of the Account in one file. *
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Account *
|
||||
mallocAccount( void )
|
||||
{
|
||||
Account *acc = (Account *)_malloc(sizeof(Account));
|
||||
|
||||
acc->flags = 0;
|
||||
acc->type = 0;
|
||||
|
||||
acc->accountName = NULL;
|
||||
acc->description = NULL;
|
||||
acc->notes = NULL;
|
||||
|
||||
acc->regData = NULL;
|
||||
acc->recnData = NULL;
|
||||
acc->adjBData = NULL;
|
||||
acc->qfRoot = mallocQuickFill();
|
||||
|
||||
acc->numTrans = 0;
|
||||
acc->transaction = NULL; /* Initially there are no transactions
|
||||
* in this account's transaction
|
||||
* array */
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
void
|
||||
freeAccount( Account *acc )
|
||||
{
|
||||
if( acc != NULL )
|
||||
{
|
||||
int i;
|
||||
|
||||
XtFree(acc->accountName);
|
||||
XtFree(acc->description);
|
||||
XtFree(acc->notes);
|
||||
|
||||
freeQuickFill(acc->qfRoot);
|
||||
|
||||
for( i=0; i<acc->numTrans; i++ )
|
||||
_free( acc->transaction[i] );
|
||||
|
||||
_free( acc->transaction );
|
||||
|
||||
_free(acc);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Transaction *
|
||||
getTransaction( Account *acc, int num )
|
||||
{
|
||||
if( acc != NULL )
|
||||
{
|
||||
if( (0 <= num) && (num < acc->numTrans) )
|
||||
return acc->transaction[num];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Transaction *
|
||||
removeTransaction( Account *acc, int num )
|
||||
{
|
||||
Transaction *trans = NULL;
|
||||
if( acc != NULL )
|
||||
{
|
||||
int i,j;
|
||||
Transaction **oldTrans = acc->transaction;
|
||||
|
||||
/* Set this flag, so we know we need to save the data file: */
|
||||
if( data != NULL )
|
||||
data->saved = False;
|
||||
|
||||
acc->numTrans--;
|
||||
acc->transaction = (Transaction **)_malloc((acc->numTrans)*
|
||||
sizeof(Transaction *));
|
||||
|
||||
trans = oldTrans[acc->numTrans];/* In case we are deleting last in
|
||||
* old array */
|
||||
for( i=0,j=0; i<acc->numTrans; i++,j++ )
|
||||
{
|
||||
if( j != num )
|
||||
acc->transaction[i] = oldTrans[j];
|
||||
else
|
||||
{
|
||||
trans = oldTrans[j];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
_free(oldTrans);
|
||||
}
|
||||
return trans;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
int
|
||||
insertTransaction( Account *acc, Transaction *trans )
|
||||
{
|
||||
int position=-1;
|
||||
|
||||
if( acc != NULL )
|
||||
{
|
||||
int i,j;
|
||||
Date *dj,*dt;
|
||||
int inserted = False;
|
||||
Transaction **oldTrans = acc->transaction;
|
||||
|
||||
/* mark the data file as needing to be saved: */
|
||||
if( data != NULL )
|
||||
data->saved = False;
|
||||
|
||||
acc->numTrans++;
|
||||
acc->transaction = (Transaction **)_malloc((acc->numTrans)*
|
||||
sizeof(Transaction *));
|
||||
|
||||
/* dt is the date of the transaction we are inserting, and dj
|
||||
* is the date of the "cursor" transaction... we want to insert
|
||||
* the new transaction before the first transaction of the same
|
||||
* or later date. The !inserted bit is a bit of a kludge to
|
||||
* make sure we only insert the new transaction once! */
|
||||
dt = &(trans->date);
|
||||
for( i=0,j=0; i<acc->numTrans; i++,j++ )
|
||||
{
|
||||
/* if we didn't do this, and we needed to insert into the
|
||||
* last spot in the array, we would walk off the end of the
|
||||
* old array, which is no good! */
|
||||
if( j>=(acc->numTrans-1) )
|
||||
{
|
||||
position = i;
|
||||
acc->transaction[i] = trans;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dj = &(oldTrans[j]->date);
|
||||
if( (datecmp(dj,dt) > 0) & !inserted )
|
||||
{
|
||||
position = i;
|
||||
acc->transaction[i] = trans;
|
||||
j--;
|
||||
inserted = True;
|
||||
}
|
||||
else
|
||||
acc->transaction[i] = oldTrans[j];
|
||||
}
|
||||
}
|
||||
|
||||
_free(oldTrans);
|
||||
}
|
||||
|
||||
if( position != -1 )
|
||||
qfInsertTransaction( acc->qfRoot, trans );
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
315
src/AdjBWindow.c
Normal file
315
src/AdjBWindow.c
Normal file
@ -0,0 +1,315 @@
|
||||
/********************************************************************\
|
||||
* AdjBWindow.c -- the adjust balance window *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "date.h"
|
||||
#include "Data.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Account.h"
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Data *data;
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
typedef struct _AdjBWindow
|
||||
{
|
||||
Account *acc; /* The account that we are adjusting */
|
||||
Widget dialog; /* The adjust balance dialog */
|
||||
Widget balance; /* Text field, the new balance */
|
||||
Widget date; /* Text field, the date for the balance */
|
||||
} AdjBWindow;
|
||||
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void adjBOkCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void adjBClose( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* adjBWindow *
|
||||
* opens up the window to adjust the balance *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* account - the account to adjust *
|
||||
* Return: recnData - the instance of this AdjBWindow *
|
||||
\********************************************************************/
|
||||
AdjBWindow *
|
||||
adjBWindow( Widget parent, Account *acc )
|
||||
{
|
||||
Widget widget, pane, controlform, actionform;
|
||||
Date date;
|
||||
AdjBWindow *adjBData;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
adjBData = (AdjBWindow *)_malloc(sizeof(AdjBWindow));
|
||||
adjBData->acc = acc;
|
||||
|
||||
/* Create the dialog box... */
|
||||
sprintf( buf, "%s: Adjust Balance", acc->accountName );
|
||||
|
||||
adjBData->dialog =
|
||||
XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNdialogStyle, XmDIALOG_APPLICATION_MODAL,
|
||||
XmNtitle, buf,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
NULL );
|
||||
|
||||
/* ... and so memory gets freed: */
|
||||
XtAddCallback( adjBData->dialog, XmNdestroyCallback,
|
||||
adjBClose, (XtPointer)adjBData );
|
||||
|
||||
/* Create a PanedWindow Manager for the dialog box... the child
|
||||
* of optiondialog the paned window is the parent of the two
|
||||
* forms which comprise the two areas of the dialog box...
|
||||
* The sash is set to minimun size to make it invisible */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, adjBData->dialog,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
/** CONTROLFORM ****************************************
|
||||
* Create a controlform for control area of dialog box */
|
||||
controlform = XtVaCreateWidget( "controlform",
|
||||
xmFormWidgetClass, pane,
|
||||
NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Date",
|
||||
xmLabelGadgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 50,
|
||||
NULL );
|
||||
|
||||
todaysDate(&date);
|
||||
sprintf(buf,"%2d/%2d/%4d\0", date.month, date.day, date.year);
|
||||
|
||||
adjBData->date =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, controlform,
|
||||
XmNvalue, buf,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 50,
|
||||
NULL );
|
||||
|
||||
/* The dateCB ensures the data entered in the date field is
|
||||
* in a valid format */
|
||||
XtAddCallback( adjBData->date, XmNmodifyVerifyCallback,
|
||||
dateCB, (XtPointer)NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "New Balance $",
|
||||
xmLabelGadgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, adjBData->date,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 50,
|
||||
NULL );
|
||||
|
||||
adjBData->balance =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, adjBData->date,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 50,
|
||||
NULL );
|
||||
|
||||
/* The amountCB ensures the data entered in the balance field is
|
||||
* in a valid format */
|
||||
XtAddCallback( adjBData->balance, XmNmodifyVerifyCallback,
|
||||
amountCB, (XtPointer)NULL );
|
||||
|
||||
XtManageChild( controlform );
|
||||
|
||||
/** ACTIONFORM ********************************************
|
||||
* Create a Form actionform for action area of dialog box */
|
||||
actionform = XtVaCreateWidget( "actionform",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, 8,
|
||||
NULL );
|
||||
|
||||
/* The OK button is anchored to the form, between divider 1 & 2
|
||||
* (in the fraction base) */
|
||||
widget = XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 1,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 3,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
adjBOkCB, (XtPointer)adjBData );
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)(adjBData->dialog) );
|
||||
|
||||
/* The cancel button! */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 3,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 5,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)(adjBData->dialog) );
|
||||
|
||||
/* A help button will pop-up context sensitive help */
|
||||
widget = XtVaCreateManagedWidget( "Help",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 5,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 7,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
helpMenubarCB, (XtPointer)HMB_ADJBWIN );
|
||||
|
||||
/* Fix action area of the pane to its current size, and not let it
|
||||
* resize. */
|
||||
XtManageChild( actionform );
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( actionform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
XtManageChild( pane );
|
||||
XtPopup( adjBData->dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
|
||||
return adjBData;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* adjBClose *
|
||||
* frees memory allocated for an adjBWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - adjBData - the data struct for this window *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
adjBClose( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
AdjBWindow *adjBData = (AdjBWindow *)cd;
|
||||
Account *acc = adjBData->acc;
|
||||
|
||||
_free(adjBData);
|
||||
acc->adjBData = NULL;
|
||||
|
||||
DEBUG("closed AdjBWindow");
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* adjBOkCB *
|
||||
* creates the new transaction to adjust the account when the *
|
||||
* user clicks "Ok" *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - adjBData - the data struct for this window *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
adjBOkCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
AdjBWindow *adjBData = (AdjBWindow *)cd;
|
||||
Transaction *trans, *tempTrans;
|
||||
Account *acc;
|
||||
String str;
|
||||
int dollar=0,cent=0;
|
||||
int pos=0;
|
||||
int amount=0,currAmount=0;
|
||||
int i;
|
||||
|
||||
data->saved = False;
|
||||
acc = adjBData->acc;
|
||||
|
||||
/* allocate mem for the new transaction */
|
||||
trans = (Transaction *)_malloc(sizeof(Transaction));
|
||||
|
||||
/* Create the "trans" transaction */
|
||||
str = XmTextGetString(adjBData->date);
|
||||
todaysDate(&(trans->date)); /* In case the date field is empty */
|
||||
sscanf( str, "%d/%d/%d", &(trans->date.month),
|
||||
&(trans->date.day), &(trans->date.year) );
|
||||
str = XmTextGetString(adjBData->balance);
|
||||
sscanf( str, "%d.%2d", &dollar, ¢ );
|
||||
amount = 100*dollar + cent;
|
||||
|
||||
/* fill out the rest of the fields */
|
||||
trans->num = XtNewString("");
|
||||
trans->memo = XtNewString("");
|
||||
trans->description = XtNewString("Adjust Balance");
|
||||
trans->catagory = 0;
|
||||
trans->reconciled = NREC;
|
||||
|
||||
pos = insertTransaction( acc, trans );
|
||||
|
||||
/* figure out what the amount for this transaction... figure out
|
||||
* the current balance, and take the diff from amount */
|
||||
for( i=0; i<pos; i++ )
|
||||
{
|
||||
tempTrans = getTransaction(acc,i);
|
||||
currAmount += tempTrans->amount;
|
||||
}
|
||||
trans->amount = amount - currAmount;
|
||||
|
||||
/* Refresh the account register window */
|
||||
regRefresh(acc->regData);
|
||||
/* Refresh the account reconcile window */
|
||||
recnRefresh(acc->recnData);
|
||||
|
||||
refreshMainWindow();
|
||||
}
|
218
src/BuildMenu.c
Normal file
218
src/BuildMenu.c
Normal file
@ -0,0 +1,218 @@
|
||||
/* Written by Dan Heller and Paula Ferguson.
|
||||
* Copyright 1994, O'Reilly & Associates, Inc.
|
||||
* Permission to use, copy, and modify this program without
|
||||
* restriction is hereby granted, as long as this copyright
|
||||
* notice appears in each copy of the program source code.
|
||||
* This program is freely distributable without licensing fees and
|
||||
* is provided without guarantee or warrantee expressed or implied.
|
||||
* This program is -not- in the public domain.
|
||||
*/
|
||||
|
||||
/* Modified by Rob Clark on Nov 26, 1995
|
||||
* Changes made: reorginization of code, and addition choice of initial
|
||||
* option menu selection
|
||||
* - moved the creation of cascade buttion for
|
||||
* option and pulldown menu till after the
|
||||
* items in the menu are created... this way
|
||||
* I can specify a widget (item in menu) to
|
||||
* be the inital choice for option menues!
|
||||
* - Added argument (int)initial to
|
||||
* facilitate choice of initial choice.
|
||||
* - modified the for loop which adds menu items.
|
||||
* If the menu item number (0,1,2,..) of the
|
||||
* menu item being created corresponds to the
|
||||
* (int)initial specified by the caller of
|
||||
* the function, then make note of the widget
|
||||
* id of menu item so we can use it to set
|
||||
* initial menu choice. If the menu item
|
||||
* created is the first menu item, make note
|
||||
* of it's widget id, in case (int)initial
|
||||
* specified by user is bigger than the number
|
||||
* of menu items.
|
||||
* - Added check to see if initial_choice was set
|
||||
* equal to a widget id. If (int)initial is
|
||||
* bigger than number of menu items, then set
|
||||
* initial_choice to = first menu item's widget
|
||||
* id, to prevent bad things from happening.
|
||||
*/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Xm/DrawingA.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/MainW.h>
|
||||
#include <Xm/FileSB.h>
|
||||
#include <Xm/MessageB.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/ScrolledW.h>
|
||||
#include <Xm/DrawnB.h>
|
||||
#include <Xm/ToggleB.h>
|
||||
#include <Xm/ToggleBG.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/PushBG.h>
|
||||
#include <Xm/CascadeBG.h>
|
||||
#include <Xm/Label.h>
|
||||
#include <Xm/LabelG.h>
|
||||
#include <Xm/Scale.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/TextF.h>
|
||||
#include <Xm/SeparatoG.h>
|
||||
|
||||
#include "BuildMenu.h"
|
||||
|
||||
/* Build popup, option and pulldown menus, depending on the menu_type.
|
||||
* It may be XmMENU_PULLDOWN, XmMENU_OPTION or XmMENU_POPUP. Pulldowns
|
||||
* return the CascadeButton that pops up the menu. Popups return the menu.
|
||||
* Option menus are created, but the RowColumn that acts as the option
|
||||
* "area" is returned unmanaged. (The user must manage it.)
|
||||
* Pulldown menus are built from cascade buttons, so this function
|
||||
* also builds pullright menus. The function also adds the right
|
||||
* callback for PushButton or ToggleButton menu items.
|
||||
*/
|
||||
Widget BuildMenu( Widget parent, int menu_type, char *menu_title,
|
||||
char menu_mnemonic, Boolean tear_off, int initial,
|
||||
MenuItem *items)
|
||||
{
|
||||
Widget menu,
|
||||
cascade,
|
||||
widget,
|
||||
first_menuitem,
|
||||
initial_choice;
|
||||
int i;
|
||||
XmString str;
|
||||
|
||||
if( menu_type == XmMENU_PULLDOWN || menu_type == XmMENU_OPTION )
|
||||
menu = XmCreatePulldownMenu( parent, "_pulldown", NULL, 0 );
|
||||
else if( menu_type == XmMENU_POPUP )
|
||||
menu = XmCreatePopupMenu( parent, "_popup", NULL, 0 );
|
||||
else
|
||||
{
|
||||
XtWarning ("Invalid menu type passed to BuildMenu()");
|
||||
return NULL;
|
||||
}
|
||||
if(tear_off)
|
||||
XtVaSetValues( menu, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL );
|
||||
|
||||
/* Now add the menu items */
|
||||
for( i=0; items[i].label != NULL; i++ )
|
||||
{
|
||||
/* If subitems exist, create the pull-right menu by calling this
|
||||
* function recursively. Since the function returns a cascade
|
||||
* button, the widget returned is used..
|
||||
*/
|
||||
if( items[i].subitems )
|
||||
{
|
||||
if( menu_type == XmMENU_OPTION )
|
||||
{
|
||||
XtWarning("You can't have submenus from option menu items.");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
widget = BuildMenu( menu, XmMENU_PULLDOWN, items[i].label,
|
||||
items[i].mnemonic, tear_off, 0,
|
||||
items[i].subitems);
|
||||
}
|
||||
else
|
||||
{
|
||||
widget = XtVaCreateManagedWidget( items[i].label,
|
||||
*(items[i].wclass), menu,
|
||||
NULL );
|
||||
}
|
||||
|
||||
/* If the current widget (menu item) being created corresponds to the
|
||||
* int that the user specified as initial choice, then set initial_choice
|
||||
* = widget. The (int)initial specified by caller of function is the
|
||||
* number of the menu item (ie, 0th, 1st, 2nd,...), but when we create
|
||||
* the cascade button a little later, we need a widget id to specify as
|
||||
* the inital choice.
|
||||
*/
|
||||
if( i == initial )
|
||||
initial_choice = widget;
|
||||
/* If this is the first menu item, set first_menuitem = widget
|
||||
* This is incase (int)initial > (number of menu items), we need to
|
||||
* set (Widget)initial_choice equal to the first menu item
|
||||
*/
|
||||
if( i == 0 )
|
||||
first_menuitem = widget;
|
||||
|
||||
/* Whether the item is a real item or a cascade button with a
|
||||
* menu, it can still have a mnemonic.
|
||||
*/
|
||||
if(items[i].mnemonic)
|
||||
XtVaSetValues( widget, XmNmnemonic, items[i].mnemonic, NULL );
|
||||
|
||||
/* any item can have an accelerator, except cascade menus. But,
|
||||
* we don't worry about that; we know better in our declarations.
|
||||
*/
|
||||
if(items[i].accelerator)
|
||||
{
|
||||
str = XmStringCreateLocalized(items[i].accel_text);
|
||||
XtVaSetValues( widget,
|
||||
XmNaccelerator, items[i].accelerator,
|
||||
XmNacceleratorText, str,
|
||||
NULL );
|
||||
XmStringFree(str);
|
||||
}
|
||||
|
||||
if( items[i].callback )
|
||||
{
|
||||
if( (items[i].wclass == &xmToggleButtonWidgetClass) ||
|
||||
(items[i].wclass == &xmToggleButtonGadgetClass) )
|
||||
{
|
||||
XtAddCallback( widget, XmNvalueChangedCallback,
|
||||
items[i].callback, items[i].callback_data );
|
||||
}
|
||||
else
|
||||
{
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
items[i].callback, items[i].callback_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the (int)initial set by user is greater than the number of menu
|
||||
* items, initial_choice will not have been set in the for loop where
|
||||
* the menu items are added. If this is the case, we will default to
|
||||
* the first menu item
|
||||
*/
|
||||
if( initial > (i-1) )
|
||||
initial_choice = first_menuitem;
|
||||
|
||||
/* Pulldown menus require a cascade button to be made */
|
||||
if( menu_type == XmMENU_PULLDOWN )
|
||||
{
|
||||
str = XmStringCreateLocalized (menu_title);
|
||||
cascade = XtVaCreateManagedWidget( menu_title,
|
||||
xmCascadeButtonGadgetClass, parent,
|
||||
XmNsubMenuId, menu,
|
||||
XmNlabelString, str,
|
||||
XmNmnemonic, menu_mnemonic,
|
||||
NULL );
|
||||
XmStringFree (str);
|
||||
}
|
||||
else if( menu_type == XmMENU_OPTION )
|
||||
{
|
||||
/* Option menus are a special case, but not hard to handle */
|
||||
Arg args[3];
|
||||
int n = 0;
|
||||
str = XmStringCreateLocalized(menu_title);
|
||||
XtSetArg( args[n], XmNsubMenuId, menu ); n++;
|
||||
XtSetArg( args[n], XmNlabelString, str ); n++;
|
||||
XtSetArg( args[n], XmNmenuHistory, initial_choice ); n++;
|
||||
/* This really isn't a cascade, but this is the widget handle
|
||||
* we're going to return at the end of the function.
|
||||
*/
|
||||
cascade = XmCreateOptionMenu( parent, menu_title, args, n );
|
||||
XmStringFree(str);
|
||||
}
|
||||
|
||||
/* for popup menus, just return the menu; pulldown menus, return
|
||||
* the cascade button; option menus, return the thing returned
|
||||
* from XmCreateOptionMenu(). This isn't a menu, or a cascade button!
|
||||
*/
|
||||
return (menu_type == XmMENU_POPUP) ? menu : cascade;
|
||||
}
|
149
src/Data.c
Normal file
149
src/Data.c
Normal file
@ -0,0 +1,149 @@
|
||||
/********************************************************************\
|
||||
* Data.c -- the main data structure of the program *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include "Data.h"
|
||||
#include "Account.h"
|
||||
#include "util.h"
|
||||
|
||||
/********************************************************************\
|
||||
* Because I can't use C++ for this project, doesn't mean that I *
|
||||
* can't pretend too! These functions perform actions on the *
|
||||
* Data data structure, in order to encapsulate the knowledge *
|
||||
* of the internals of the Data in one file. *
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Data *
|
||||
mallocData( void )
|
||||
{
|
||||
Data *data = (Data *)_malloc(sizeof(Data));
|
||||
|
||||
data->saved = True;
|
||||
data->new = False;
|
||||
|
||||
data->numAcc = 0;
|
||||
data->account = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
void
|
||||
freeData( Data *data )
|
||||
{
|
||||
if( data != NULL )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; i<data->numAcc; i++ )
|
||||
freeAccount( data->account[i] );
|
||||
|
||||
_free( data->account );
|
||||
|
||||
_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Account *
|
||||
getAccount( Data *data, int num )
|
||||
{
|
||||
if( data != NULL )
|
||||
{
|
||||
if( (0 <= num) && (num < data->numAcc) )
|
||||
return data->account[num];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Account *
|
||||
removeAccount( Data *data, int num )
|
||||
{
|
||||
Account *acc = NULL;
|
||||
|
||||
if( data != NULL )
|
||||
{
|
||||
int i,j;
|
||||
Account **oldAcc = data->account;
|
||||
|
||||
data->saved = False;
|
||||
|
||||
data->numAcc--;
|
||||
data->account = (Account **)_malloc((data->numAcc)*sizeof(Account *));
|
||||
|
||||
acc = oldAcc[data->numAcc]; /* In case we are deleting last in
|
||||
* old array */
|
||||
for( i=0,j=0; i<data->numAcc; i++,j++ )
|
||||
{
|
||||
if( j != num )
|
||||
data->account[i] = oldAcc[j];
|
||||
else
|
||||
{
|
||||
acc = oldAcc[j];
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
_free(oldAcc);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
int
|
||||
insertAccount( Data *data, Account *acc )
|
||||
{
|
||||
int i=-1;
|
||||
|
||||
if( data != NULL )
|
||||
{
|
||||
Account **oldAcc = data->account;
|
||||
|
||||
data->saved = False;
|
||||
|
||||
data->numAcc++;
|
||||
data->account = (Account **)_malloc((data->numAcc)*sizeof(Account *));
|
||||
|
||||
for( i=0; i<(data->numAcc-1); i++ )
|
||||
data->account[i] = oldAcc[i];
|
||||
|
||||
data->account[i] = acc;
|
||||
|
||||
_free(oldAcc);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
144
src/FileBox.c
Normal file
144
src/FileBox.c
Normal file
@ -0,0 +1,144 @@
|
||||
/********************************************************************\
|
||||
* FileBox.c -- the file dialog box *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/FileSB.h>
|
||||
#include "FileBox.h"
|
||||
#include "util.h"
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern XtAppContext app;
|
||||
Boolean done=True;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void fileBoxCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* fileBox *
|
||||
* pops up a file selection dialog (either a "Save As" or an *
|
||||
* "Open"), and returns the name of the file the users selected. *
|
||||
* (This function does not return until the user selects a file *
|
||||
* or pressed "Cancel") *
|
||||
* *
|
||||
* NOTE: fileBox is not re-entrant... if an instance of fileBox *
|
||||
* already exists, the latter call will return NULL *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* type - either OPEN or SAVE *
|
||||
* Return: none *
|
||||
* Global: app - the XtAppContext *
|
||||
* done - whether fileBox should return *
|
||||
\********************************************************************/
|
||||
char *
|
||||
fileBox( Widget parent, int type )
|
||||
{
|
||||
Widget dialog;
|
||||
char* fileName = NULL;
|
||||
XmString filterpattern = XmStringCreateSimple( "*.dat" ),
|
||||
dialogname;
|
||||
|
||||
if( !done )
|
||||
return NULL; /* Don't open if there already is
|
||||
* an instance of fileBox */
|
||||
|
||||
done = False;
|
||||
|
||||
ENTER("fileBox");
|
||||
|
||||
// setBusyCursor( parent );
|
||||
|
||||
if( type == OPEN )
|
||||
{
|
||||
dialogname = XmStringCreateSimple( "Open" );
|
||||
dialog = XmCreateFileSelectionDialog( parent, "Open", NULL, 0 );
|
||||
}
|
||||
else if( type == SAVE )
|
||||
{
|
||||
dialogname = XmStringCreateSimple( "Save" );
|
||||
dialog = XmCreateFileSelectionDialog( parent, "Save", NULL, 0 );
|
||||
}
|
||||
|
||||
XtVaSetValues( dialog,
|
||||
XmNpattern, filterpattern,
|
||||
XmNdialogTitle, dialogname,
|
||||
XmNminWidth, 350,
|
||||
XmNminHeight, 350,
|
||||
NULL );
|
||||
|
||||
XtUnmanageChild( XmFileSelectionBoxGetChild(dialog,XmDIALOG_HELP_BUTTON) );
|
||||
|
||||
/* Add the "ok" button callbacks... first save the name, then
|
||||
* destroy the dialog */
|
||||
XtAddCallback( dialog, XmNokCallback,
|
||||
fileBoxCB, (XtPointer)&fileName );
|
||||
XtAddCallback( dialog, XmNokCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
/* Add the cancel button callback */
|
||||
XtAddCallback( dialog, XmNcancelCallback,
|
||||
fileBoxCB, (XtPointer)NULL );
|
||||
XtAddCallback( dialog, XmNcancelCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
XmStringFree( filterpattern );
|
||||
|
||||
XtManageChild( dialog );
|
||||
|
||||
// unsetBusyCursor( parent );
|
||||
/* while the user hasn't pushed "Ok", simulate XtMainLoop.*/
|
||||
while( !done || XtAppPending(app) )
|
||||
XtAppProcessEvent( app, XtIMAll );
|
||||
|
||||
LEAVE("fileBox");
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* fileBoxCB *
|
||||
* callback that saves the name of the file so that fileBox *
|
||||
* can return *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - fileName *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: done - whether fileBox should return *
|
||||
\********************************************************************/
|
||||
void
|
||||
fileBoxCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
char **fileName = (char **)cd;
|
||||
ENTER("fileBoxCB");
|
||||
|
||||
if( cd != NULL )
|
||||
{
|
||||
XmFileSelectionBoxCallbackStruct *cbs =
|
||||
(XmFileSelectionBoxCallbackStruct *)cb;
|
||||
|
||||
if( !XmStringGetLtoR(cbs->value,charset,fileName) )
|
||||
*fileName = NULL;
|
||||
}
|
||||
done = True;
|
||||
LEAVE("fileBoxCB");
|
||||
}
|
615
src/FileIO.c
Normal file
615
src/FileIO.c
Normal file
@ -0,0 +1,615 @@
|
||||
/********************************************************************\
|
||||
* FileIO.c -- read from and writing to a datafile for xacc *
|
||||
* (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
* *
|
||||
* *
|
||||
* NOTE: the readxxxx/writexxxx functions changed the current *
|
||||
* position in the file, and so the order which these *
|
||||
* functions are called in important *
|
||||
* *
|
||||
* the format of the data in the file: *
|
||||
* file ::== token numAccounts (Account)^numAccounts *
|
||||
* Account ::== flags type accountName description notes *
|
||||
* numTran (Transaction)^numTrans *
|
||||
* Transaction ::== num date description memo catagory reconciled *
|
||||
* amount *
|
||||
* token ::== int [the version of file format == VERSION] *
|
||||
* numTrans ::== int *
|
||||
* numAccounts ::== int *
|
||||
* flags ::== char *
|
||||
* type ::== char *
|
||||
* accountName ::== String *
|
||||
* description ::== String *
|
||||
* notes ::== String *
|
||||
* num ::== String *
|
||||
* date ::== Date *
|
||||
* description ::== String *
|
||||
* memo ::== String *
|
||||
* catagory ::== int *
|
||||
* reconciled ::== char *
|
||||
* amount ::== int *
|
||||
* String ::== size (char)^size *
|
||||
* size ::== int *
|
||||
* Date ::== year month day *
|
||||
* month ::== int *
|
||||
* day ::== int *
|
||||
* year ::== int *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <fcntl.h>
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "Account.h"
|
||||
#include "Data.h"
|
||||
|
||||
#define PERMS 0666
|
||||
#define WFLAGS (O_WRONLY | O_CREAT | O_TRUNC)
|
||||
#define RFLAGS O_RDONLY
|
||||
#define VERSION 1
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Widget toplevel;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
Account *readAccount( int fd, int token );
|
||||
Transaction *readTransaction( int fd, int token );
|
||||
char *readString( int fd, int token );
|
||||
Date *readDate( int fd, int token );
|
||||
|
||||
int writeAccount( int fd, Account *account );
|
||||
int writeTransaction( int fd, Transaction *trans );
|
||||
int writeString( int fd, char *str );
|
||||
int writeDate( int fd, Date *date );
|
||||
|
||||
/********************************************************************\
|
||||
********************** LOAD DATA ***********************************
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* readData *
|
||||
* reads in the data from file datafile *
|
||||
* *
|
||||
* Args: datafile - the file to load the data from *
|
||||
* Return: the struct with the program data in it *
|
||||
\********************************************************************/
|
||||
Data *
|
||||
readData( char *datafile )
|
||||
{
|
||||
int fd;
|
||||
int numAcc;
|
||||
int err=0;
|
||||
int token=0;
|
||||
int i;
|
||||
Data *data = mallocData();
|
||||
|
||||
fd = open( datafile, RFLAGS, 0 );
|
||||
if( fd == -1 )
|
||||
{
|
||||
ERROR();
|
||||
freeData(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read in the file format token */
|
||||
err = read( fd, &token, sizeof(int) );
|
||||
if( err == -1 )
|
||||
{
|
||||
ERROR();
|
||||
close(fd);
|
||||
freeData(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If this is an old file, ask the user if the file
|
||||
* should be updated */
|
||||
if( token < VERSION )
|
||||
{
|
||||
char msg[BUFSIZE];
|
||||
sprintf( (char *)&msg, FILE_TOO_OLD_MSG );
|
||||
if( !verifyBox( toplevel, msg ) )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If this is a newer file than we know how to deal
|
||||
* with, warn the user */
|
||||
if( token > VERSION )
|
||||
{
|
||||
char msg[BUFSIZE];
|
||||
sprintf( (char *)&msg, FILE_TOO_NEW_MSG );
|
||||
if( !verifyBox( toplevel, msg ) )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read numAccs */
|
||||
err = read( fd, &numAcc, sizeof(int) );
|
||||
if( err == -1 )
|
||||
{
|
||||
close(fd);
|
||||
freeData(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read in the accounts */
|
||||
for( i=0; i<numAcc; i++ )
|
||||
{
|
||||
Account *acc;
|
||||
acc = readAccount( fd, token );
|
||||
if( acc == NULL )
|
||||
{
|
||||
close(fd);
|
||||
printf(" numAcc = %d\n i = %d\n",numAcc,i);
|
||||
return data;
|
||||
}
|
||||
else
|
||||
insertAccount( data, acc );
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return data;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* readAccount *
|
||||
* reads in the data for an account from the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* token - the datafile version *
|
||||
* Return: the account structure *
|
||||
\********************************************************************/
|
||||
Account *
|
||||
readAccount( int fd, int token )
|
||||
{
|
||||
int err=0;
|
||||
int i;
|
||||
int numTrans;
|
||||
Account *acc = mallocAccount();
|
||||
|
||||
err = read( fd, &(acc->flags), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &(acc->type), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acc->accountName = readString( fd, token );
|
||||
if( acc->accountName == NULL )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acc->description = readString( fd, token );
|
||||
if( acc->accountName == NULL )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acc->notes = readString( fd, token );
|
||||
if( acc->accountName == NULL )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &numTrans, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
freeAccount(acc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read the transactions */
|
||||
for( i=0; i<numTrans; i++ )
|
||||
{
|
||||
Transaction *trans;
|
||||
trans = readTransaction( fd, token );
|
||||
if( trans == NULL )
|
||||
{
|
||||
printf(" numTrans = %d\n i = %d\n",numTrans,i);
|
||||
return acc;
|
||||
}
|
||||
else
|
||||
insertTransaction( acc, trans );
|
||||
}
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* readTransaction *
|
||||
* reads in the data for a transaction from the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* token - the datafile version *
|
||||
* Return: the transaction structure *
|
||||
\********************************************************************/
|
||||
Transaction *
|
||||
readTransaction( int fd, int token )
|
||||
{
|
||||
int err=0;
|
||||
Date *date;
|
||||
Transaction *trans = (Transaction *)_malloc(sizeof(Transaction));
|
||||
|
||||
trans->num = readString( fd, token );
|
||||
if( trans->num == NULL )
|
||||
{
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
date = readDate( fd, token );
|
||||
if( date == NULL )
|
||||
{
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
trans->date = *date;
|
||||
_free(date);
|
||||
|
||||
trans->description = readString( fd, token );
|
||||
if( trans->description == NULL )
|
||||
{
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
trans->memo = readString( fd, token );
|
||||
if( trans->memo == NULL )
|
||||
{
|
||||
XtFree(trans->description);
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &(trans->catagory), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
XtFree(trans->memo);
|
||||
XtFree(trans->description);
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &(trans->reconciled), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
{
|
||||
XtFree(trans->memo);
|
||||
XtFree(trans->description);
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* What used to be reconciled, is now cleared... transactions
|
||||
* aren't reconciled until you get your bank statement, and
|
||||
* use the reconcile window to mark the transaction reconciled */
|
||||
if( token == 0 )
|
||||
if( trans->reconciled == YREC )
|
||||
trans->reconciled = CREC;
|
||||
|
||||
/* make sure the value of trans->reconciled is valid...
|
||||
* I have to do this mainly for if I change what NREC and
|
||||
* YREC are defined to be... this way it might loose all
|
||||
* the reconciled data, but at least the field is valid */
|
||||
if( (trans->reconciled != YREC) && (trans->reconciled != CREC) )
|
||||
trans->reconciled = NREC;
|
||||
|
||||
err = read( fd, &(trans->amount), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
XtFree(trans->memo);
|
||||
XtFree(trans->description);
|
||||
XtFree(trans->num);
|
||||
_free(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* readString *
|
||||
* reads in a string (char *) from the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* token - the datafile version *
|
||||
* Return: the string *
|
||||
\********************************************************************/
|
||||
char *
|
||||
readString( int fd, int token )
|
||||
{
|
||||
int err=0;
|
||||
int size;
|
||||
char *str;
|
||||
|
||||
err = read( fd, &size, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return NULL;
|
||||
|
||||
str = (char *)XtMalloc(size);
|
||||
err = read( fd, str, size );
|
||||
if( err != size )
|
||||
{
|
||||
printf( " size = %d\n err = %d\n str = %s\n", size, err, str );
|
||||
_free(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* readDate *
|
||||
* reads in a Date struct from the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* token - the datafile version *
|
||||
* Return: the Date struct *
|
||||
\********************************************************************/
|
||||
Date *
|
||||
readDate( int fd, int token )
|
||||
{
|
||||
int err=0;
|
||||
Date *date = (Date *)_malloc(sizeof(Date));
|
||||
|
||||
err = read( fd, &(date->year), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
_free(date);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &(date->month), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
_free(date);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read( fd, &(date->day), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
_free(date);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
********************** SAVE DATA ***********************************
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* writeData *
|
||||
* flattens the program data and saves it in a file *
|
||||
* *
|
||||
* Args: datafile - the file to store the data in *
|
||||
* Return: -1 on failure *
|
||||
\********************************************************************/
|
||||
int
|
||||
writeData( char *datafile, Data *data )
|
||||
{
|
||||
int i,numAcc;
|
||||
int err = 0;
|
||||
int token = VERSION; /* The file format version */
|
||||
int fd;
|
||||
|
||||
fd = open( datafile, WFLAGS, PERMS );
|
||||
if( fd == -1 )
|
||||
{
|
||||
ERROR();
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = write( fd, &token, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
{
|
||||
ERROR();
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
numAcc = data->numAcc;
|
||||
err = write( fd, &numAcc, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
for( i=0; i<numAcc; i++ )
|
||||
{
|
||||
err = writeAccount( fd, getAccount(data,i) );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* writeAccount *
|
||||
* saves the data for an account to the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* acc - the account data to save *
|
||||
* Return: -1 on failure *
|
||||
\********************************************************************/
|
||||
int
|
||||
writeAccount( int fd, Account *acc )
|
||||
{
|
||||
Transaction *trans;
|
||||
int err=0;
|
||||
int i,numTrans;
|
||||
|
||||
err = write( fd, &(acc->flags), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, &(acc->type), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
return -1;
|
||||
|
||||
err = writeString( fd, acc->accountName );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = writeString( fd, acc->description );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = writeString( fd, acc->notes );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
/* figure out numTrans */
|
||||
for( numTrans = 0; getTransaction(acc,numTrans) != NULL; numTrans++ )
|
||||
{}
|
||||
|
||||
err = write( fd, &numTrans, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
for( i=0; i<numTrans; i++ )
|
||||
{
|
||||
err = writeTransaction( fd, getTransaction(acc,i) );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* writeTransaction *
|
||||
* saves the data for a transaction to the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* trans - the transaction data to save *
|
||||
* Return: -1 on failure *
|
||||
\********************************************************************/
|
||||
int
|
||||
writeTransaction( int fd, Transaction *trans )
|
||||
{
|
||||
int err=0;
|
||||
|
||||
err = writeString( fd, trans->num );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = writeDate( fd, &(trans->date) );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = writeString( fd, trans->description );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = writeString( fd, trans->memo );
|
||||
if( err == -1 )
|
||||
return err;
|
||||
|
||||
err = write( fd, &(trans->catagory), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, &(trans->reconciled), sizeof(char) );
|
||||
if( err != sizeof(char) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, &(trans->amount), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* writeString *
|
||||
* saves a string to the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* str - the String to save *
|
||||
* Return: -1 on failure *
|
||||
\********************************************************************/
|
||||
int
|
||||
writeString( int fd, char *str )
|
||||
{
|
||||
int err=0;
|
||||
int size;
|
||||
|
||||
for( size=0; str[size] != '\0'; size++ )
|
||||
{}
|
||||
size++; /* we want to make sure we include the '\0'!
|
||||
* Otherwise, bad things happen */
|
||||
|
||||
err = write( fd, &size, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, str, size );
|
||||
if( err != size )
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* writeDate *
|
||||
* saves a Date to the datafile *
|
||||
* *
|
||||
* Args: fd - the filedescriptor of the data file *
|
||||
* date - the Date to save *
|
||||
* Return: -1 on failure *
|
||||
\********************************************************************/
|
||||
int
|
||||
writeDate( int fd, Date *date )
|
||||
{
|
||||
int err=0;
|
||||
|
||||
err = write( fd, &(date->year), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, &(date->month), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
err = write( fd, &(date->day), sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
}
|
487
src/HelpWindow.c
Normal file
487
src/HelpWindow.c
Normal file
@ -0,0 +1,487 @@
|
||||
/********************************************************************\
|
||||
* HelpWindow.c -- a help window for hypertext help. *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#define USEDEBUG
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <X11/xpm.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "HTML.h"
|
||||
|
||||
/********************************************************************\
|
||||
* HTML History functions *
|
||||
\********************************************************************/
|
||||
typedef struct _HTMLHistory {
|
||||
char *htmlfile;
|
||||
struct _HTMLHistory *last;
|
||||
struct _HTMLHistory *next;
|
||||
} HTMLHistory;
|
||||
|
||||
/* insert an htmlfile into history. Return TRUE if this
|
||||
* is the first element in the history. If not last element
|
||||
* in history, all next pages are deleted */
|
||||
int
|
||||
historyInsert( HTMLHistory **history, char *htmlfile )
|
||||
{
|
||||
if( (*history) != NULL )
|
||||
{
|
||||
HTMLHistory *temp;
|
||||
|
||||
/* delete all next pages: */
|
||||
while( (*history)->next != NULL )
|
||||
{
|
||||
temp = (*history)->next;
|
||||
|
||||
(*history)->next = temp->next;
|
||||
_free(temp->htmlfile);
|
||||
_free(temp);
|
||||
}
|
||||
|
||||
/* Add new node to history: */
|
||||
temp = (HTMLHistory *)_malloc(sizeof(HTMLHistory));
|
||||
temp->htmlfile = (char *)_malloc((strlen(htmlfile)+1)*sizeof(char));
|
||||
sprintf(temp->htmlfile,"%s",htmlfile);
|
||||
temp->next = NULL;
|
||||
temp->last = (*history);
|
||||
(*history) = temp;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This must be the first node in the history... */
|
||||
(*history) = (HTMLHistory *)_malloc(sizeof(HTMLHistory));
|
||||
(*history)->htmlfile = (char *)_malloc((strlen(htmlfile)+1)*sizeof(char));
|
||||
sprintf((*history)->htmlfile,"%s",htmlfile);
|
||||
(*history)->last = NULL;
|
||||
(*history)->next = NULL;
|
||||
|
||||
/* ...so return TRUE */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move forward in history, and return current htmlfile */
|
||||
char *
|
||||
historyFwd( HTMLHistory **history )
|
||||
{
|
||||
if( (*history) != NULL )
|
||||
{
|
||||
if( (*history)->next != NULL )
|
||||
(*history) = (*history)->next;
|
||||
return (*history)->htmlfile;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Move back in history, and return current htmlfile */
|
||||
char *
|
||||
historyBack( HTMLHistory **history )
|
||||
{
|
||||
if( (*history) != NULL )
|
||||
{
|
||||
if( (*history)->last != NULL )
|
||||
(*history) = (*history)->last;
|
||||
return (*history)->htmlfile;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return current htmlfile */
|
||||
char *
|
||||
historyCurrent( HTMLHistory **history )
|
||||
{
|
||||
if( (*history) != NULL )
|
||||
return (*history)->htmlfile;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove all entries from history: */
|
||||
void
|
||||
historyClear( HTMLHistory **history )
|
||||
{
|
||||
/* move to beginning of history: */
|
||||
while( (*history)->last != NULL )
|
||||
(*history) = (*history)->last;
|
||||
|
||||
/* delete all next pages: */
|
||||
while( (*history)->next != NULL )
|
||||
{
|
||||
HTMLHistory *temp = (*history)->next;
|
||||
|
||||
(*history)->next = temp->next;
|
||||
_free(temp->htmlfile);
|
||||
_free(temp);
|
||||
}
|
||||
|
||||
/* delete current page: */
|
||||
_free((*history)->htmlfile);
|
||||
_free(*history);
|
||||
(*history) = NULL;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* Help Window stuff... *
|
||||
\********************************************************************/
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
Widget helpwidget;
|
||||
HTMLHistory *helpHistory = NULL;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
static void closeHelpWin( Widget mw, XtPointer cd, XtPointer cb );
|
||||
static void helpBackCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
static void helpFwdCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
static void helpAnchorCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
char *htmlRead( char *file );
|
||||
ImageInfo *htmlResolveImage( Widget wm, char *file, int nl );
|
||||
|
||||
/********************************************************************\
|
||||
* helpWindow *
|
||||
* opens up a help window, and displays html *
|
||||
* *
|
||||
* Args: parent - the parent widget *
|
||||
* title - the title of the window *
|
||||
* htmlfile - the file name of the help file to display *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
helpWindow( Widget parent, char *title, char *htmlfile )
|
||||
{
|
||||
Widget dialog,
|
||||
pane,
|
||||
controlform,
|
||||
actionform,
|
||||
widget;
|
||||
int position=0;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* if the help window isn't open, then open it... otherwise, load
|
||||
* new help page into current help window */
|
||||
if( historyInsert(&helpHistory,htmlfile) )
|
||||
{
|
||||
/* Create the dialog box... XmNdeleteResponse is set to
|
||||
* XmDESTROY so the dialog's memory is freed when it is closed */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNdialogStyle, XmDIALOG_APPLICATION_MODAL,
|
||||
XmNtitle, title,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNminWidth, 500,
|
||||
XmNminHeight, 400,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( dialog, XmNdestroyCallback, closeHelpWin, NULL );
|
||||
|
||||
/* Create a PanedWindow Manager for the dialog box... the child
|
||||
* of optiondialog the paned window is the parent of the two
|
||||
* forms which comprise the two areas of the dialog box...
|
||||
* The sash is set to minimun size to make it invisible */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, dialog,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
/** CONTROLFORM ****************************************
|
||||
* Create a controlform for control area of dialog box */
|
||||
controlform = XtVaCreateWidget( "frame",
|
||||
xmFrameWidgetClass, pane,
|
||||
NULL );
|
||||
|
||||
helpwidget =
|
||||
XtVaCreateManagedWidget( "help",
|
||||
htmlWidgetClass, controlform,
|
||||
WbNresolveImageFunction, htmlResolveImage,
|
||||
WbNdelayImageLoads, False,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( helpwidget, WbNanchorCallback, helpAnchorCB, NULL );
|
||||
|
||||
XtManageChild( controlform );
|
||||
|
||||
/* we have to load the page after the widget is realized, so
|
||||
* the pictures can be drawn */
|
||||
XtVaSetValues( helpwidget, WbNtext, htmlRead(htmlfile), NULL );
|
||||
|
||||
/** ACTIONFORM ********************************************
|
||||
* Create a Form actionform for action area of dialog box */
|
||||
actionform = XtVaCreateWidget( "actionform",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, 7,
|
||||
NULL );
|
||||
position=0;
|
||||
|
||||
/* The "Back" button */
|
||||
widget = XtVaCreateManagedWidget( "Back",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, ++position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback, helpBackCB, NULL );
|
||||
|
||||
/* The "Forward" button */
|
||||
widget = XtVaCreateManagedWidget( "Forward",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, ++position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback, helpFwdCB, NULL );
|
||||
|
||||
/* The "Close" button */
|
||||
widget = XtVaCreateManagedWidget( "Close",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, ++position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback, destroyShellCB, dialog );
|
||||
|
||||
/* Fix action area of the pane to its current size, and not let it
|
||||
* resize. */
|
||||
XtManageChild( actionform );
|
||||
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( actionform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
XtManageChild( pane );
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
}
|
||||
/* if help window is already open, just load new page */
|
||||
else
|
||||
XtVaSetValues( helpwidget, WbNtext, htmlRead(htmlfile), NULL );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* callback functions... *
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* helpBackCB - called when user clicks "Back" button... shows last *
|
||||
* help page in history *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
static void
|
||||
helpBackCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
char *file = historyBack(&helpHistory);
|
||||
if( file != NULL )
|
||||
{
|
||||
XtVaSetValues( helpwidget,
|
||||
WbNtext, htmlRead(file),
|
||||
NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* helpFwdCB - called when user clicks "Forward" button... shows *
|
||||
* next help page in the history *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
static void
|
||||
helpFwdCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
char *file = historyFwd(&helpHistory);
|
||||
if( file != NULL )
|
||||
{
|
||||
XtVaSetValues( helpwidget,
|
||||
WbNtext, htmlRead(file),
|
||||
NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* closeHelpWin - called when the help window is closed *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
static void
|
||||
closeHelpWin( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
/* Delete the history: */
|
||||
historyClear(&helpHistory);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* helpAnchorCB - called when user clicks on html anchor tag *
|
||||
* *
|
||||
* Args: mw - the html widget that called us *
|
||||
* cd - *
|
||||
* cb - the anchor call-back struct *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
static void
|
||||
helpAnchorCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
WbAnchorCallbackData *acbs = (WbAnchorCallbackData *)cb;
|
||||
|
||||
fprintf(stderr,"%d %s\n",acbs->element_id, acbs->text);
|
||||
|
||||
if( historyInsert(&helpHistory,acbs->href) )
|
||||
{ERROR();} /* CB shouldn't be called if there is not history!!! */
|
||||
else
|
||||
XtVaSetValues( mw, WbNtext, htmlRead(acbs->href), NULL );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* HTML functions... *
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* htmlRead *
|
||||
* *
|
||||
* Args: file - the name of the html file to read *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
char *
|
||||
htmlRead( char *file )
|
||||
{
|
||||
char *buf=NULL;
|
||||
char filename[BUFSIZE];
|
||||
int size=0;
|
||||
int fd;
|
||||
|
||||
sprintf( (char *)&filename, "%s/%s", HELP_ROOT, file );
|
||||
/* Open file: */
|
||||
fd = open( filename, O_RDONLY );
|
||||
if( fd == -1 )
|
||||
{
|
||||
ERROR();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find size: */
|
||||
size = lseek( fd, 0, SEEK_END );
|
||||
lseek( fd, 0, SEEK_SET );
|
||||
|
||||
/* Allocate memory... don't use _malloc(), `cause it is
|
||||
* freed elsewhere */
|
||||
buf = (char *)malloc(size*sizeof(char));
|
||||
|
||||
/* read in file */
|
||||
if( read(fd,buf,size) == -1 )
|
||||
{
|
||||
free(buf);
|
||||
buf=NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* htmlResolveImage *
|
||||
* *
|
||||
* Args: mw - the html widge *
|
||||
* file - the name of the html file to read *
|
||||
* nl - ??? *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
extern Widget toplevel;
|
||||
|
||||
ImageInfo *
|
||||
htmlResolveImage( Widget mw, char *file, int nl )
|
||||
{
|
||||
ImageInfo *img = (ImageInfo *)malloc(sizeof(ImageInfo));
|
||||
XpmImage xpm;
|
||||
XpmAttributes attr;
|
||||
int err,i;
|
||||
char filename[BUFSIZE];
|
||||
|
||||
sprintf( (char *)&filename, "%s/%s", HELP_ROOT, file );
|
||||
|
||||
/* initialize stuff: */
|
||||
memset( img, 0, sizeof(ImageInfo) );
|
||||
memset( &attr, 0, sizeof(XpmAttributes) );
|
||||
memset( &xpm, 0, sizeof(XpmImage) );
|
||||
|
||||
err = XpmReadFileToXpmImage( filename, &xpm, NULL );
|
||||
img->width = xpm.width;
|
||||
img->height = xpm.height;
|
||||
img->num_colors = xpm.ncolors;
|
||||
img->image_data = None;
|
||||
|
||||
err = XpmCreatePixmapFromXpmImage( XtDisplay(mw), XtWindow(mw), &xpm,
|
||||
&(img->image), NULL, NULL );
|
||||
if( err != 0 )
|
||||
ERROR();
|
||||
|
||||
return img;
|
||||
}
|
698
src/MainWindow.c
Normal file
698
src/MainWindow.c
Normal file
@ -0,0 +1,698 @@
|
||||
/********************************************************************\
|
||||
* MainWindow.c -- the main window, and associated helper functions *
|
||||
* and callback functions for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/MainW.h>
|
||||
#include <Xm/Label.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
#include <Xm/List.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "Data.h"
|
||||
#include "Account.h"
|
||||
#include "FileIO.h"
|
||||
#include "FileBox.h"
|
||||
#include "BuildMenu.h"
|
||||
#include "MainWindow.h"
|
||||
#include "RegWindow.h"
|
||||
#include "XferWindow.h"
|
||||
#include "HelpWindow.h"
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void closeMainWindow( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void listCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void fileMenubarCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void accountMenubarCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void helpMenubarCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Data *data;
|
||||
extern char *datafile;
|
||||
extern Widget toplevel;
|
||||
int row; /* The selected row of accountlist */
|
||||
Widget accountlist;
|
||||
char *type[] = { "Bank","Cash","Asset","Credit Card",
|
||||
"Liability","Portfolio","Mutual Fund" };
|
||||
/* Pixel values are used to color the balance field text
|
||||
* when computing the balance */
|
||||
#ifndef USE_NO_COLOR
|
||||
# define POSITIVE_BALANCE "black"
|
||||
# define NEGATIVE_BALANCE "red"
|
||||
Pixel posPixel, negPixel;
|
||||
Boolean havePixels = False;
|
||||
#endif
|
||||
|
||||
/********************************************************************\
|
||||
* refreshMainWindow *
|
||||
* *
|
||||
* Args: none *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
* accountlist - the widget that has the list of accounts *
|
||||
\********************************************************************/
|
||||
void
|
||||
refreshMainWindow( void )
|
||||
{
|
||||
int i,j,nrows;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
XtVaGetValues( accountlist, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixDeleteRows( accountlist, 0, nrows );
|
||||
|
||||
/* Add all the accounts to the list */
|
||||
for( i=0; i<data->numAcc; i++ )
|
||||
{
|
||||
String rows[3];
|
||||
Transaction *trans=NULL;
|
||||
Account *acc = getAccount( data, i );
|
||||
int balance = 0;
|
||||
|
||||
j=0;
|
||||
while( (trans = getTransaction(acc,j++)) != NULL )
|
||||
balance += trans->amount;
|
||||
|
||||
if( balance < 0 )
|
||||
sprintf( buf,"-$%d.%02d\0", ABS(balance/100), ABS(balance % 100) );
|
||||
else
|
||||
sprintf( buf,"$%d.%02d\0", ABS(balance/100), ABS(balance % 100) );
|
||||
|
||||
rows[0] = acc->accountName;
|
||||
rows[1] = type[acc->type];
|
||||
rows[2] = XtNewString(buf);
|
||||
XtVaGetValues( accountlist, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixAddRows( accountlist, nrows, rows, NULL, NULL, 1 );
|
||||
|
||||
#ifndef USE_NO_COLOR
|
||||
/* Set the color of the text, depending on whether the
|
||||
* balance is negative or positive */
|
||||
if( balance < 0 )
|
||||
XbaeMatrixSetCellColor( accountlist, nrows, 2, negPixel );
|
||||
else
|
||||
XbaeMatrixSetCellColor( accountlist, nrows, 2, posPixel );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* mainWindow -- the main window... (normally) the first window *
|
||||
* that pops up. Has list of accounts that the user can open. *
|
||||
* Opening an account produces a register window. The user *
|
||||
* can also create new accounts and edit existing accounts. *
|
||||
* *
|
||||
* Args: parent - the parent of the window to be created *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
* accountlist - the widget that has the list of accounts *
|
||||
\********************************************************************/
|
||||
void
|
||||
mainWindow( Widget parent )
|
||||
{
|
||||
Widget mainwindow,menubar,actionform,controlform,pane,widget;
|
||||
int position;
|
||||
|
||||
/******************************************************************\
|
||||
* Set up the menubar *
|
||||
\******************************************************************/
|
||||
MenuItem fileMenu[] = {
|
||||
{ "New File...", &xmPushButtonWidgetClass, 'N', NULL, NULL,
|
||||
fileMenubarCB, (XtPointer)FMB_NEW, (MenuItem *)NULL },
|
||||
{ "Open File... ",&xmPushButtonWidgetClass, 'O', NULL, NULL,
|
||||
fileMenubarCB, (XtPointer)FMB_OPEN, (MenuItem *)NULL },
|
||||
{ "", &xmSeparatorWidgetClass, 0, NULL, NULL,
|
||||
NULL, NULL, (MenuItem *)NULL },
|
||||
{ "Save", &xmPushButtonWidgetClass, 'S', NULL, NULL,
|
||||
fileMenubarCB, (XtPointer)FMB_SAVE, (MenuItem *)NULL },
|
||||
{ "Save As...", &xmPushButtonWidgetClass, 'A', NULL, NULL,
|
||||
fileMenubarCB, (XtPointer)FMB_SAVEAS,(MenuItem *)NULL },
|
||||
{ "", &xmSeparatorWidgetClass, 0, NULL, NULL,
|
||||
NULL, NULL, (MenuItem *)NULL },
|
||||
{ "Quit", &xmPushButtonWidgetClass, 'Q', NULL, NULL,
|
||||
fileMenubarCB, (XtPointer)FMB_QUIT, (MenuItem *)NULL },
|
||||
NULL,
|
||||
};
|
||||
|
||||
MenuItem accountMenu[] = {
|
||||
{ "New Account...", &xmPushButtonWidgetClass, 'N', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_NEW, (MenuItem *)NULL },
|
||||
{ "Open Account", &xmPushButtonWidgetClass, 'O', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_OPEN, (MenuItem *)NULL },
|
||||
{ "Edit Account...", &xmPushButtonWidgetClass, 'E', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_EDIT, (MenuItem *)NULL },
|
||||
{ "Delete Account...", &xmPushButtonWidgetClass, 'D', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_DEL, (MenuItem *)NULL },
|
||||
{ "", &xmSeparatorWidgetClass, 0, NULL, NULL,
|
||||
NULL, NULL, (MenuItem *)NULL },
|
||||
{ "Transfer", &xmPushButtonWidgetClass, 'C', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_TRNS, (MenuItem *)NULL },
|
||||
{ "Report", &xmPushButtonWidgetClass, 'R', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_RPRT, (MenuItem *)NULL },
|
||||
#if 0
|
||||
{ "Edit Categories...", &xmPushButtonWidgetClass, 'C', NULL, NULL,
|
||||
accountMenubarCB, (XtPointer)AMB_CAT, (MenuItem *)NULL },
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
MenuItem helpMenu[] = {
|
||||
{ "About...", &xmPushButtonWidgetClass, 'A', NULL, NULL,
|
||||
helpMenubarCB, (XtPointer)HMB_ABOUT, (MenuItem *)NULL },
|
||||
{ "Help...", &xmPushButtonWidgetClass, 'H', NULL, NULL,
|
||||
helpMenubarCB, (XtPointer)HMB_MAIN, (MenuItem *)NULL },
|
||||
{ "", &xmSeparatorWidgetClass, 0, NULL, NULL,
|
||||
NULL, NULL, (MenuItem *)NULL },
|
||||
{ "License...", &xmPushButtonWidgetClass, 'L', NULL, NULL,
|
||||
helpMenubarCB, (XtPointer)HMB_LIC, (MenuItem *)NULL },
|
||||
NULL,
|
||||
};
|
||||
|
||||
mainwindow = XtVaCreateManagedWidget( "mainwindow",
|
||||
xmMainWindowWidgetClass, parent,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
NULL );
|
||||
|
||||
/* Umm... this doesn't seem to be getting called */
|
||||
XtAddCallback( mainwindow, XmNdestroyCallback,
|
||||
closeMainWindow, (XtPointer)NULL );
|
||||
|
||||
menubar = XmCreateMenuBar( mainwindow, "menubar", NULL, 0 );
|
||||
|
||||
BuildMenu( menubar, XmMENU_PULLDOWN, "File", 'F', False, 0, fileMenu );
|
||||
BuildMenu( menubar, XmMENU_PULLDOWN, "Account",'A', False, 0, accountMenu );
|
||||
BuildMenu( menubar, XmMENU_PULLDOWN, "Help", 'H', False, 0, helpMenu );
|
||||
|
||||
XtManageChild( menubar );
|
||||
|
||||
/******************************************************************\
|
||||
* If they haven't already been initialize, initialize the Pixel *
|
||||
* values that are used for foreground colors for the balance *
|
||||
\******************************************************************/
|
||||
#ifndef USE_NO_COLOR
|
||||
if( !havePixels )
|
||||
{
|
||||
XrmValue colorValue, pixelValue;
|
||||
|
||||
colorValue.size = strlen(POSITIVE_BALANCE);
|
||||
colorValue.addr = (XtPointer)POSITIVE_BALANCE;
|
||||
pixelValue.size = sizeof(Pixel);
|
||||
pixelValue.addr = (XtPointer)0;
|
||||
|
||||
XtConvertAndStore( parent,
|
||||
XtRString, &colorValue,
|
||||
XtRPixel, &pixelValue );
|
||||
|
||||
posPixel = (*(Pixel *)pixelValue.addr);
|
||||
|
||||
colorValue.size = strlen(NEGATIVE_BALANCE);
|
||||
colorValue.addr = (XtPointer)NEGATIVE_BALANCE;
|
||||
pixelValue.size = sizeof(Pixel);
|
||||
pixelValue.addr = (XtPointer)0;
|
||||
|
||||
XtConvertAndStore( parent,
|
||||
XtRString, &colorValue,
|
||||
XtRPixel, &pixelValue );
|
||||
|
||||
negPixel = (*(Pixel *)pixelValue.addr);
|
||||
|
||||
havePixels = True;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a PanedWindow Manager for the dialog box... the paned
|
||||
* window is the parent of the two forms which comprise the two
|
||||
* areas of the dialog box */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, mainwindow,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
|
||||
/******************************************************************\
|
||||
* The account list -- the top part of the window *
|
||||
\******************************************************************/
|
||||
|
||||
/* form to help place the accountlist */
|
||||
actionform = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, pane,
|
||||
NULL );
|
||||
|
||||
/* Create a matrix widget to hold the account list... the
|
||||
* listCB helps make this matrix think it is a list. We
|
||||
* use the matrix instead of a list to get the accounts
|
||||
* up in columns */
|
||||
{
|
||||
String labels[3] = {"Account Name","Type","Balance"};
|
||||
short colWidths[] = {16,10,8};
|
||||
unsigned char alignments[3] = {XmALIGNMENT_BEGINNING,
|
||||
XmALIGNMENT_CENTER,
|
||||
XmALIGNMENT_END};
|
||||
|
||||
accountlist
|
||||
= XtVaCreateWidget( "list",
|
||||
xbaeMatrixWidgetClass, actionform,
|
||||
XmNvisibleRows, 7,
|
||||
XmNcolumns, 3,
|
||||
XmNcolumnWidths, colWidths,
|
||||
XmNcolumnAlignments, alignments,
|
||||
XmNcolumnLabels, labels,
|
||||
XmNtraversalOn, False,
|
||||
XmNfill, True,
|
||||
XmNcellMarginHeight, 0,
|
||||
XmNcellMarginWidth, 0,
|
||||
XmNgridType, XmGRID_NONE,
|
||||
XmNcellShadowThickness, 0,
|
||||
XmNverticalScrollBarDisplayPolicy,XmDISPLAY_STATIC,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL);
|
||||
XtAddCallback( accountlist, XmNenterCellCallback,
|
||||
listCB, (XtPointer)NULL );
|
||||
|
||||
/* If the user double-clicks on an account in the list, open
|
||||
* up the detail view (ie the regWindow, or whatever) for
|
||||
* that type of account */
|
||||
XtAddCallback( accountlist, XmNdefaultActionCallback,
|
||||
accountMenubarCB, (XtPointer)AMB_OPEN );
|
||||
}
|
||||
|
||||
refreshMainWindow();
|
||||
XtManageChild(accountlist);
|
||||
|
||||
/******************************************************************\
|
||||
* The button area -- has buttons to create a new account, or *
|
||||
* delete an account, or whatever other button I think up *
|
||||
* NOTE: the buttons are just shortcuts to the account menubar, *
|
||||
* and this is why all the callbacks are accountMenubarCB *
|
||||
\******************************************************************/
|
||||
|
||||
/* create form that will contain most everything in this window...
|
||||
* The fractionbase divides the form into segments, so we have
|
||||
* better control over where to put the buttons */
|
||||
controlform = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, 5,
|
||||
NULL );
|
||||
|
||||
position = 0; /* puts the buttons in the right place */
|
||||
|
||||
/* The "Open" button */
|
||||
widget = XtVaCreateManagedWidget( "Open",
|
||||
xmPushButtonWidgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
accountMenubarCB, (XtPointer)AMB_OPEN );
|
||||
|
||||
/* The "New" button, to create a new account */
|
||||
widget = XtVaCreateManagedWidget( "New",
|
||||
xmPushButtonWidgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
accountMenubarCB, (XtPointer)AMB_NEW );
|
||||
|
||||
/* The "Edit" button */
|
||||
widget = XtVaCreateManagedWidget( "Edit",
|
||||
xmPushButtonWidgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
accountMenubarCB, (XtPointer)AMB_EDIT );
|
||||
|
||||
/* The "Delete" button */
|
||||
widget = XtVaCreateManagedWidget( "Delete",
|
||||
xmPushButtonWidgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
accountMenubarCB, (XtPointer)AMB_DEL );
|
||||
|
||||
|
||||
/* Fix button area of the pane to its current size, and not let
|
||||
* it resize. */
|
||||
XtManageChild( controlform );
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( controlform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
/* Fix action area of the pane to its current size, and not let
|
||||
* it resize. */
|
||||
XtManageChild( actionform );
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( accountlist, XmNheight, &h, NULL );
|
||||
XtVaSetValues( actionform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
XtManageChild(pane);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* closeMainWindow *
|
||||
* frees memory allocated for an regWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
closeMainWindow( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
|
||||
DEBUG("closed MainWindow");
|
||||
DEBUGCMD(printf(" coresize = %d\n",_coresize()));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* listCB -- makes the matrix widget behave like a list widget *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: accountlist - the widget that has the list of accounts *
|
||||
\********************************************************************/
|
||||
void
|
||||
listCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XbaeMatrixEnterCellCallbackStruct *cbs =
|
||||
(XbaeMatrixEnterCellCallbackStruct *)cb;
|
||||
int rows = XbaeMatrixNumRows(accountlist);
|
||||
|
||||
cbs->doit = False;
|
||||
cbs->map = False;
|
||||
|
||||
row = cbs->row;
|
||||
XbaeMatrixDeselectAll(accountlist);
|
||||
XbaeMatrixSelectRow( accountlist, row );
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* fileMenubarCB -- handles file menubar choices *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - const that lets us know which choice was selected *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
* datafile - the name of the user's datafile *
|
||||
* toplevel - the toplevel widget *
|
||||
\********************************************************************/
|
||||
void
|
||||
fileMenubarCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int button = (int)cd;
|
||||
|
||||
/*
|
||||
* which of the file menubar options was chosen
|
||||
* FMB_NEW - New datafile
|
||||
* FMB_OPEN - Open datfile
|
||||
* FMB_SAVE - Save datafile
|
||||
* FMB_SAVEAS - Save datafile As
|
||||
* FMB_QUIT - Quit
|
||||
*/
|
||||
|
||||
switch( button )
|
||||
{
|
||||
case FMB_NEW:
|
||||
DEBUG("FMB_NEW");
|
||||
if( (!(data->saved)) && (datafile != NULL) )
|
||||
{
|
||||
char *msg = SAVE_MSG;
|
||||
if( verifyBox(toplevel,msg) )
|
||||
fileMenubarCB( mw, (XtPointer)FMB_SAVE, cb );
|
||||
}
|
||||
datafile = NULL;
|
||||
freeData(data);
|
||||
data = mallocData();
|
||||
data->new = True; /* so we have to do a "SaveAs" when
|
||||
* the file is first saved */
|
||||
break;
|
||||
case FMB_OPEN:
|
||||
DEBUG("FMB_OPEN");
|
||||
if( (!(data->saved)) && (datafile != NULL) )
|
||||
{
|
||||
char *msg = SAVE_MSG;
|
||||
if( verifyBox(toplevel,msg) )
|
||||
fileMenubarCB( mw, (XtPointer)FMB_SAVE, cb );
|
||||
}
|
||||
freeData(data);
|
||||
while( (datafile = fileBox(toplevel,OPEN)) == NULL )
|
||||
printf("Bad File\n");
|
||||
|
||||
/* load the accounts from the users datafile */
|
||||
data = readData(datafile);
|
||||
|
||||
if( data == NULL )
|
||||
{
|
||||
/* the file could not be found */
|
||||
data = mallocData();
|
||||
}
|
||||
|
||||
break;
|
||||
case FMB_SAVE:
|
||||
DEBUG("FMB_SAVE");
|
||||
/* ??? Somehow make sure all in-progress edits get committed! */
|
||||
writeData( datafile, data );
|
||||
data->saved = True;
|
||||
break;
|
||||
case FMB_SAVEAS:
|
||||
DEBUG("FMB_SAVEAS");
|
||||
while( (datafile = fileBox(toplevel,OPEN)) == NULL )
|
||||
printf("Bad File\n");
|
||||
fileMenubarCB( mw, (XtPointer)FMB_SAVE, cb );
|
||||
break;
|
||||
case FMB_QUIT:
|
||||
DEBUG("FMB_QUIT");
|
||||
{
|
||||
Account *acc;
|
||||
int i=0;
|
||||
while( (acc=getAccount(data,i++)) != NULL )
|
||||
{
|
||||
if( acc->regData != NULL )
|
||||
{
|
||||
/* ??? */
|
||||
acc->regData = NULL;
|
||||
}
|
||||
if( acc->recnData != NULL )
|
||||
{
|
||||
/* ??? */
|
||||
acc->recnData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( (!(data->saved)) && (datafile != NULL) )
|
||||
{
|
||||
char *msg = SAVE_MSG;
|
||||
if( verifyBox(toplevel,msg) )
|
||||
fileMenubarCB( mw, (XtPointer)FMB_SAVE, cb );
|
||||
}
|
||||
|
||||
freeData(data);
|
||||
XtUnmapWidget(toplevel); /* make it disappear quickly */
|
||||
XtDestroyWidget(toplevel);
|
||||
return; /* to avoid the refreshMainWindow */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG("We shouldn't be here!");
|
||||
}
|
||||
refreshMainWindow();
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* accountMenubarCB -- handles account menubar choices *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - const that lets us know which choice was selected *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
* row - the selected row number *
|
||||
* toplevel - the toplevel widget *
|
||||
\********************************************************************/
|
||||
void
|
||||
accountMenubarCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int button = (int)cd;
|
||||
int *posList;
|
||||
int numPos;
|
||||
|
||||
/*
|
||||
* which of the file menubar options was chosen
|
||||
* AMB_NEW - New account
|
||||
* AMB_OPEN - Open account
|
||||
* AMB_EDIT - Edit account
|
||||
* AMB_DEL - Delete account
|
||||
* AMB_CAT - Edit catagories
|
||||
*/
|
||||
|
||||
switch( button )
|
||||
{
|
||||
case AMB_NEW:
|
||||
DEBUG("AMB_NEW");
|
||||
accWindow(toplevel);
|
||||
break;
|
||||
case AMB_OPEN:
|
||||
DEBUG("AMB_OPEN");
|
||||
{
|
||||
Account *acc = getAccount(data,row);
|
||||
if( acc->regData == NULL )
|
||||
acc->regData = regWindow( toplevel, acc );
|
||||
}
|
||||
break;
|
||||
case AMB_EDIT:
|
||||
DEBUG("AMB_EDIT");
|
||||
editAccWindow( toplevel, getAccount(data,row) );
|
||||
break;
|
||||
case AMB_DEL:
|
||||
DEBUG("AMB_DEL");
|
||||
{
|
||||
char *msg = "Are you sure you want to delete this account?";
|
||||
if( verifyBox(toplevel,msg) )
|
||||
{
|
||||
freeAccount( removeAccount(data,row) );
|
||||
refreshMainWindow();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AMB_TRNS:
|
||||
DEBUG("AMB_TRNS");
|
||||
xferWindow(toplevel);
|
||||
break;
|
||||
case AMB_RPRT:
|
||||
DEBUG("AMB_RPRT");
|
||||
simpleReportWindow(toplevel);
|
||||
break;
|
||||
case AMB_CAT:
|
||||
DEBUG("AMB_CAT");
|
||||
break;
|
||||
default:
|
||||
DEBUG("We shouldn't be here!");
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* helpMenubarCB -- handles help menubar choices *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - const that lets us know which choice was selected *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: toplevel - the toplevel widget *
|
||||
\********************************************************************/
|
||||
void
|
||||
helpMenubarCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int button = (int)cd;
|
||||
int *posList;
|
||||
int numPos;
|
||||
|
||||
/*
|
||||
* which of the file menubar options was chosen
|
||||
* HMB_ABOUT - About this program
|
||||
* HMB_MAIN - Display help window for the main window
|
||||
* HMB_REGWIN - Display help window for the Register Window
|
||||
* HMB_RECNWIN - Display help window for the Reconcile Window
|
||||
* HMB_LIC - GPL Licence info
|
||||
*/
|
||||
|
||||
switch( button )
|
||||
{
|
||||
case HMB_ABOUT:
|
||||
DEBUG("HMB_ABOUT");
|
||||
helpWindow( toplevel, "About", HH_ABOUT );
|
||||
break;
|
||||
case HMB_REGWIN:
|
||||
/* When the user selects "Help" in the RegWindow */
|
||||
DEBUG("HMB_REGWIN");
|
||||
helpWindow( toplevel, "Help", HH_REGWIN );
|
||||
break;
|
||||
case HMB_RECNWIN:
|
||||
/* When the user selects "Help" in the RecnWindow */
|
||||
DEBUG("HMB_RECNWIN");
|
||||
helpWindow( toplevel, "Help", HH_RECNWIN );
|
||||
break;
|
||||
case HMB_ADJBWIN:
|
||||
/* When the user selects "Help" in the AdjBWindow */
|
||||
DEBUG("HMB_ADJBWIN");
|
||||
helpWindow( toplevel, "Help", HH_ADJBWIN );
|
||||
break;
|
||||
case HMB_MAIN:
|
||||
/* When the user selects "Help" in the MainWindow */
|
||||
DEBUG("HMB_HELP");
|
||||
helpWindow( toplevel, "Help", HH_MAIN );
|
||||
break;
|
||||
case HMB_LIC:
|
||||
/* The GNU Public License */
|
||||
DEBUG("HMB_LIC");
|
||||
helpWindow( toplevel, "License", HH_GPL );
|
||||
break;
|
||||
default:
|
||||
DEBUG("We shouldn't be here!");
|
||||
}
|
||||
}
|
56
src/Makefile
Normal file
56
src/Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
######################################################################
|
||||
#********************************************************************
|
||||
#* Makefile -- makefile for xacc (X-Accountant) *
|
||||
#* Copyright (C) 1997 Robin D. Clark *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or *
|
||||
#* modify it under the terms of the GNU General Public License as *
|
||||
#* published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU General Public License*
|
||||
#* along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
#* *
|
||||
#* Author: Rob Clark *
|
||||
#* Internet: rclark@cs.hmc.edu *
|
||||
#* Address: 609 8th Street *
|
||||
#* Huntington Beach, CA 92648-4632 *
|
||||
#********************************************************************
|
||||
|
||||
######################################################################
|
||||
# DO NOT EDIT THE STUFF BELOW THIS LINE! #
|
||||
|
||||
OBJS = main.o util.o date.o MainWindow.o RegWindow.o BuildMenu.o \
|
||||
AccWindow.o FileIO.o Account.o Data.o XferWindow.o FileBox.o \
|
||||
QuickFill.o Reports.o RecnWindow.o HelpWindow.o AdjBWindow.o
|
||||
|
||||
SRCS = ${OBJS:.o=.c}
|
||||
|
||||
TARGET = ../xacc
|
||||
|
||||
default: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS) ../libhtmlw/libhtmlw.a
|
||||
@echo "++++++"
|
||||
$(CC) $(OBJS) $(LFLAGS) $(LIBS) ../libhtmlw/libhtmlw.a -o $@
|
||||
|
||||
.c.o: Makefile
|
||||
@echo "+++"
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) -- $(SRCS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ *.bak
|
||||
|
||||
really_clean:
|
||||
makedepend -- --
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
129
src/QuickFill.c
Normal file
129
src/QuickFill.c
Normal file
@ -0,0 +1,129 @@
|
||||
/********************************************************************\
|
||||
* QuickFill.h -- the quickfill tree data structure *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "Account.h"
|
||||
#include "date.h"
|
||||
#include "QuickFill.h"
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void qfInsertTransactionRec( QuickFill *qf, Transaction *trans, int depth );
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* Because I can't use C++ for this project, doesn't mean that I *
|
||||
* can't pretend too! These functions perform actions on the *
|
||||
* QuickFill tree structure, in order to encapsulate the knowledge *
|
||||
* of the internals of QuickFill into one file. *
|
||||
\********************************************************************/
|
||||
|
||||
inline int
|
||||
CHAR_TO_INDEX( char c )
|
||||
{
|
||||
c = toupper(c)-0x40;
|
||||
if( (c < 0) || (c >= QFNUM) )
|
||||
return 0;
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
QuickFill *
|
||||
mallocQuickFill( void )
|
||||
{
|
||||
int i;
|
||||
QuickFill *qf = (QuickFill *)_malloc(sizeof(QuickFill));
|
||||
|
||||
for( i=0; i<QFNUM; i++ )
|
||||
qf->qf[i] = NULL;
|
||||
|
||||
qf->trans = NULL;
|
||||
|
||||
return qf;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
void
|
||||
freeQuickFill( QuickFill *qf )
|
||||
{
|
||||
if( qf != NULL )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; i<QFNUM; i++ )
|
||||
freeQuickFill( qf->qf[i] );
|
||||
|
||||
_free(qf);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
QuickFill *
|
||||
getQuickFill( QuickFill *qf, char c )
|
||||
{
|
||||
if( qf != NULL )
|
||||
{
|
||||
DEBUGCMD(printf(" index = %d\n",CHAR_TO_INDEX(c)));
|
||||
return qf->qf[CHAR_TO_INDEX(c)];
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
void
|
||||
qfInsertTransaction( QuickFill *qf, Transaction *trans )
|
||||
{
|
||||
qfInsertTransactionRec( qf, trans, 0 );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
void
|
||||
qfInsertTransactionRec( QuickFill *qf, Transaction *trans, int depth )
|
||||
{
|
||||
if( qf != NULL )
|
||||
{
|
||||
if( trans->description[depth] != '\0' )
|
||||
{
|
||||
int index = CHAR_TO_INDEX( trans->description[depth] );
|
||||
|
||||
if( qf->qf[index] == NULL )
|
||||
qf->qf[index] = mallocQuickFill();
|
||||
|
||||
qf->qf[index]->trans = trans;
|
||||
|
||||
qfInsertTransactionRec( qf->qf[index], trans, ++depth );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
841
src/RecnWindow.c
Normal file
841
src/RecnWindow.c
Normal file
@ -0,0 +1,841 @@
|
||||
/********************************************************************\
|
||||
* RecnWindow.c -- the reconcile window *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
|
||||
#include "Data.h"
|
||||
#include "Account.h"
|
||||
#include "RegWindow.h"
|
||||
#include "MainWindow.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
typedef struct _RecnWindow
|
||||
{
|
||||
Account *acc; /* The account that we are reconciling */
|
||||
int diff; /* The amount ($$$) to reconcile */
|
||||
Widget dialog; /* The reconcile window dialog */
|
||||
Widget difference; /* Text field, amount left to reconcile */
|
||||
Widget totDebit; /* Text field, total debit reconciled */
|
||||
Widget totCredit; /* Text field, total credit reconciled */
|
||||
Widget debit; /* Debit matrix show unreconciled debit */
|
||||
Widget credit; /* Credit matrix, shows credits... */
|
||||
} RecnWindow;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void recnRecalculateBalance( RecnWindow *recnData );
|
||||
|
||||
void recnClose( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void recnOkCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void recnCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Data *data;
|
||||
extern XtAppContext app;
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* recnRefresh *
|
||||
* refreshes the transactions in the reconcile window *
|
||||
* *
|
||||
* Args: recnData -- the reconcile window to refresh *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
recnRefresh( RecnWindow *recnData )
|
||||
{
|
||||
if( recnData != NULL )
|
||||
{
|
||||
int i,nrows;
|
||||
char buf[BUFSIZE];
|
||||
Transaction *trans;
|
||||
|
||||
/* NOTE: an improvement of the current design would be to use the
|
||||
* user-data in the rows to detect where transactions need
|
||||
* to be inserted/delete, instead of deleting and re-inserting
|
||||
* all the transactions! */
|
||||
|
||||
/* Delete all the entries in the debit matrix */
|
||||
XtVaGetValues( recnData->debit, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixDeleteRows( recnData->debit, 0, nrows );
|
||||
|
||||
/* Delete all the entries in the credit matrix */
|
||||
XtVaGetValues( recnData->credit, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixDeleteRows( recnData->credit, 0, nrows );
|
||||
|
||||
/* Add the non-reconciled transactions */
|
||||
i=0;
|
||||
while( (trans=getTransaction(recnData->acc,i++)) != NULL )
|
||||
{
|
||||
String rows[5];
|
||||
|
||||
if( trans->reconciled != YREC )
|
||||
{
|
||||
sprintf( buf, "%c", trans->reconciled );
|
||||
rows[0] = XtNewString(buf);
|
||||
rows[1] = trans->num;
|
||||
sprintf( buf, "%2d/%2d/%02d\0",
|
||||
trans->date.month,
|
||||
trans->date.day,
|
||||
(trans->date.year%100) );
|
||||
rows[2] = XtNewString(buf);
|
||||
rows[3] = trans->description;
|
||||
sprintf( buf, "%d.%02d\0",
|
||||
ABS(trans->amount/100),
|
||||
ABS(trans->amount % 100) );
|
||||
rows[4] = XtNewString(buf);
|
||||
|
||||
if( trans->amount < 0 )
|
||||
{
|
||||
XtVaGetValues( recnData->debit, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixAddRows( recnData->debit, nrows, rows, NULL, NULL, 1 );
|
||||
XbaeMatrixSetRowUserData( recnData->debit, nrows, (XtPointer)trans );
|
||||
}
|
||||
else
|
||||
{
|
||||
XtVaGetValues( recnData->credit, XmNrows, &nrows, NULL );
|
||||
XbaeMatrixAddRows( recnData->credit, nrows, rows, NULL, NULL, 1 );
|
||||
XbaeMatrixSetRowUserData( recnData->credit,nrows, (XtPointer)trans );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recnRecalculateBalance(recnData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* recnRecalculateBalance *
|
||||
* refreshes the balances in the reconcile window *
|
||||
* *
|
||||
* Args: recnData -- the reconcile window to refresh *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
recnRecalculateBalance( RecnWindow *recnData )
|
||||
{
|
||||
Transaction *trans;
|
||||
char buf[BUFSIZE];
|
||||
int i,nrows;
|
||||
int debit = 0;
|
||||
int credit = 0;
|
||||
int diff = 0;
|
||||
|
||||
/* Calculate the total debit: */
|
||||
XtVaGetValues( recnData->debit, XmNrows, &nrows, NULL );
|
||||
for( i=0; i<nrows; i++ )
|
||||
{
|
||||
String recn = XbaeMatrixGetCell( recnData->debit, i, 0 );
|
||||
if( recn[0] == YREC )
|
||||
{
|
||||
trans = (Transaction *)XbaeMatrixGetRowUserData( recnData->debit, i );
|
||||
debit += trans->amount;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the total credit: */
|
||||
XtVaGetValues( recnData->credit, XmNrows, &nrows, NULL );
|
||||
for( i=0; i<nrows; i++ )
|
||||
{
|
||||
String recn = XbaeMatrixGetCell( recnData->credit, i, 0 );
|
||||
if( recn[0] == YREC )
|
||||
{
|
||||
trans = (Transaction *)XbaeMatrixGetRowUserData( recnData->credit, i );
|
||||
credit += trans->amount;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the difference field, and the total fields */
|
||||
sprintf( buf, " $ %d.%02d\0",
|
||||
ABS(debit/100), ABS(debit%100) );
|
||||
XmTextSetString( recnData->totDebit, buf );
|
||||
|
||||
sprintf( buf, " $ %d.%02d\0",
|
||||
(credit/100), ABS(credit%100) );
|
||||
XmTextSetString( recnData->totCredit, buf );
|
||||
|
||||
diff = recnData->diff + credit + debit;
|
||||
if( diff < 0 )
|
||||
sprintf( buf, "-$ %d.%02d\0",
|
||||
ABS(diff/100), ABS(diff%100) );
|
||||
else
|
||||
sprintf( buf, " $ %d.%02d\0",
|
||||
(diff/100), ABS(diff%100) );
|
||||
XmTextSetString( recnData->difference, buf );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* startRecnWindow: gets the ending balance for reconcile window *
|
||||
\********************************************************************/
|
||||
void
|
||||
startRecnOkCB( Widget wm, XtPointer cd, XtPointer cb )
|
||||
{ *(int *)cd = 1; }
|
||||
void
|
||||
startRecnCancelCB( Widget wm, XtPointer cd, XtPointer cb )
|
||||
{ *(int *)cd = 0; }
|
||||
|
||||
/********************************************************************\
|
||||
* startRecnWindow *
|
||||
* opens up the window to prompt the user to enter the ending *
|
||||
* balance from bank statement *
|
||||
* *
|
||||
* NOTE: This dialog does not return until the user presses "Ok" *
|
||||
* or "Cancel" *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* acc - the account to reconcile *
|
||||
* diff - returns the amount from ending balance field *
|
||||
* Return: True, if the user presses "Ok", else False *
|
||||
* Global: app - the app context *
|
||||
\********************************************************************/
|
||||
Boolean
|
||||
startRecnWindow( Widget parent, Account *acc, int *diff )
|
||||
{
|
||||
Widget dialog,
|
||||
pane,
|
||||
controlform,
|
||||
actionform,
|
||||
widget, endB, newB;
|
||||
Transaction *trans;
|
||||
char buf[BUFSIZE];
|
||||
int j, endBalance;
|
||||
int done=-1;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* Figure out previous ending balance: */
|
||||
endBalance=0;
|
||||
j=0;
|
||||
while( (trans = getTransaction(acc,j++)) != NULL )
|
||||
if( trans->reconciled == YREC )
|
||||
endBalance += trans->amount;
|
||||
|
||||
/* Create the dialog box... XmNdeleteResponse is set to
|
||||
* XmDESTROY so the dialog's memory is freed when it is closed */
|
||||
sprintf( buf, "%s: Reconcile", acc->accountName );
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNdialogStyle, XmDIALOG_APPLICATION_MODAL,
|
||||
XmNtitle, buf,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNminWidth, 250,
|
||||
XmNminHeight, 150,
|
||||
NULL );
|
||||
|
||||
/* Create a PanedWindow Manager for the dialog box... the child
|
||||
* of optiondialog the paned window is the parent of the two
|
||||
* forms which comprise the two areas of the dialog box...
|
||||
* The sash is set to minimun size to make it invisible */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, dialog,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
/** CONTROLFORM ****************************************
|
||||
* Create a controlform for control area of dialog box */
|
||||
controlform = XtVaCreateWidget( "controlform",
|
||||
xmFormWidgetClass, pane,
|
||||
NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Previous Balance: $",
|
||||
xmLabelGadgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 50,
|
||||
NULL );
|
||||
|
||||
sprintf( buf, "%d.%02d", (endBalance/100), ABS(endBalance%100) );
|
||||
endB = XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, controlform,
|
||||
XmNvalue, buf,
|
||||
XmNeditable, False,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 50,
|
||||
NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Ending Balance: $",
|
||||
xmLabelGadgetClass, controlform,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, endB,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 50,
|
||||
NULL );
|
||||
|
||||
newB = XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, controlform,
|
||||
XmNeditable, True,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, endB,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 50,
|
||||
NULL );
|
||||
|
||||
/* The amountCB ensures the data entered in the amount field is
|
||||
* in a valid format */
|
||||
XtAddCallback( newB, XmNmodifyVerifyCallback,
|
||||
amountCB, (XtPointer)NULL );
|
||||
|
||||
XtManageChild( controlform );
|
||||
|
||||
/** ACTIONFORM ********************************************
|
||||
* Create a Form actionform for action area of dialog box */
|
||||
actionform = XtVaCreateWidget( "actionform",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, 8,
|
||||
NULL );
|
||||
|
||||
/* The OK button is anchored to the form, between divider 1 & 2
|
||||
* (in the fraction base) */
|
||||
widget = XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 1,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 3,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
startRecnOkCB, (XtPointer)&done );
|
||||
|
||||
/* The cancel button! */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 3,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 5,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
startRecnCancelCB, (XtPointer)&done );
|
||||
|
||||
/* A help button will pop-up context sensitive help */
|
||||
widget = XtVaCreateManagedWidget( "Help",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 5,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 7,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
helpMenubarCB, (XtPointer)HMB_RECNWIN );
|
||||
|
||||
/* Fix action area of the pane to its current size, and not let it
|
||||
* resize. */
|
||||
XtManageChild( actionform );
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( actionform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
XtManageChild( pane );
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
|
||||
/* while the user hasn't pushed "Ok", simulate XtMainLoop. */
|
||||
while( (done == -1) || XtAppPending(app) )
|
||||
XtAppProcessEvent( app, XtIMAll );
|
||||
|
||||
/* Get the amount from the "end-balance" field */
|
||||
{
|
||||
String str;
|
||||
int dollar=0,cent=0;
|
||||
str = XmTextGetString(newB);
|
||||
sscanf( str, "%d.%2d", &dollar, ¢ );
|
||||
*diff = endBalance - (100*dollar + cent);
|
||||
}
|
||||
|
||||
XtDestroyWidget(dialog);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* recnWindow *
|
||||
* opens up the window to reconcile an account *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* account - the account to reconcile *
|
||||
* Return: recnData - the instance of this RecnWindow *
|
||||
\********************************************************************/
|
||||
RecnWindow *
|
||||
recnWindow( Widget parent, Account *acc )
|
||||
{
|
||||
Widget pane, form, widget;
|
||||
int position;
|
||||
char title[BUFSIZE];
|
||||
RecnWindow *recnData;
|
||||
int diff;
|
||||
|
||||
/* Popup a little window to prompt the user to enter the
|
||||
* ending balance for his/her bank statement */
|
||||
if( !startRecnWindow(parent,acc,&diff) )
|
||||
return NULL;
|
||||
|
||||
setBusyCursor(parent);
|
||||
|
||||
recnData = (RecnWindow *)_malloc(sizeof(RecnWindow));
|
||||
recnData->acc = acc;
|
||||
recnData->diff = diff;
|
||||
|
||||
sprintf( title, "%s: Reconcile", acc->accountName );
|
||||
|
||||
/* force the size of the dialog so it is not resizable */
|
||||
recnData->dialog =
|
||||
XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNtitle, title,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( recnData->dialog, XmNdestroyCallback,
|
||||
recnClose, (XtPointer)recnData );
|
||||
|
||||
/* The reconcile window is a paned window, with the top pane
|
||||
* used for the Debits, and Credits matrices, and the bottom pane
|
||||
* has the misc stuff, like "New Balance" field, "Difference" field,
|
||||
* and the buttons. The Debit/Credit pane have a matrix, and a
|
||||
* "total" field */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, recnData->dialog,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The top pane has the debit and credit matrices *
|
||||
\******************************************************************/
|
||||
{
|
||||
Widget frame, rowcol;
|
||||
short colWidths[] = {1,5,8,20,8}; /* the widths of columns */
|
||||
String labels[] = {"","Num","Date","Description","Amount"};
|
||||
unsigned char alignments[] = {XmALIGNMENT_CENTER,
|
||||
XmALIGNMENT_END,
|
||||
XmALIGNMENT_CENTER,
|
||||
XmALIGNMENT_BEGINNING,
|
||||
XmALIGNMENT_END};
|
||||
|
||||
rowcol = XtVaCreateWidget( "rowcol",
|
||||
xmRowColumnWidgetClass, pane,
|
||||
XmNnumColumns, 2,
|
||||
XmNorientation, XmHORIZONTAL,
|
||||
NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The "Debits" area *
|
||||
\******************************************************************/
|
||||
form = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, rowcol,
|
||||
NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Debits:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
NULL );
|
||||
|
||||
frame = XtVaCreateWidget( "frame",
|
||||
xmFrameWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, widget,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
recnData->debit =
|
||||
XtVaCreateWidget( "recn",
|
||||
xbaeMatrixWidgetClass, frame,
|
||||
XmNfixedRows, 0,
|
||||
XmNfixedColumns, 0,
|
||||
XmNrows, 1,
|
||||
XmNvisibleRows, 10,
|
||||
XmNfill, True,
|
||||
XmNcolumns, 5,
|
||||
XmNcolumnLabels, labels,
|
||||
XmNcolumnWidths, colWidths,
|
||||
XmNcolumnAlignments, alignments,
|
||||
XmNtraverseFixedCells, False,
|
||||
XmNgridType, XmGRID_SHADOW_IN,
|
||||
XmNshadowType, XmSHADOW_ETCHED_IN,
|
||||
XmNverticalScrollBarDisplayPolicy,XmDISPLAY_STATIC,
|
||||
XmNselectScrollVisible, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( recnData->debit, XmNenterCellCallback,
|
||||
recnCB, (XtPointer)recnData );
|
||||
|
||||
XtManageChild(recnData->debit);
|
||||
widget = XtVaCreateManagedWidget( "Total:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
NULL );
|
||||
|
||||
recnData->totDebit =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNeditable, False,
|
||||
XmNmarginHeight, 1,
|
||||
XmNmarginWidth, 1,
|
||||
XmNmaxLength, 10,
|
||||
XmNcolumns, 10,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 20,
|
||||
NULL );
|
||||
|
||||
XtManageChild(frame);
|
||||
XtManageChild(form);
|
||||
|
||||
/******************************************************************\
|
||||
* The "Credits" area *
|
||||
\******************************************************************/
|
||||
form = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, rowcol,
|
||||
NULL );
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Credits:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
NULL );
|
||||
|
||||
frame = XtVaCreateWidget( "frame",
|
||||
xmFrameWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, widget,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
recnData->credit =
|
||||
XtVaCreateWidget( "recn",
|
||||
xbaeMatrixWidgetClass, frame,
|
||||
XmNfixedRows, 0,
|
||||
XmNfixedColumns, 0,
|
||||
XmNrows, 1,
|
||||
XmNvisibleRows, 10,
|
||||
XmNfill, True,
|
||||
XmNcolumns, 5,
|
||||
XmNcolumnLabels, labels,
|
||||
XmNcolumnWidths, colWidths,
|
||||
XmNcolumnAlignments, alignments,
|
||||
XmNtraverseFixedCells, False,
|
||||
XmNgridType, XmGRID_SHADOW_IN,
|
||||
XmNshadowType, XmSHADOW_ETCHED_IN,
|
||||
XmNverticalScrollBarDisplayPolicy,XmDISPLAY_STATIC,
|
||||
XmNselectScrollVisible, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( recnData->credit, XmNenterCellCallback,
|
||||
recnCB, (XtPointer)recnData );
|
||||
|
||||
XtManageChild(recnData->credit);
|
||||
widget = XtVaCreateManagedWidget( "Total:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
NULL );
|
||||
|
||||
recnData->totCredit =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNeditable, False,
|
||||
XmNmarginHeight, 1,
|
||||
XmNmarginWidth, 1,
|
||||
XmNmaxLength, 10,
|
||||
XmNcolumns, 10,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 20,
|
||||
NULL );
|
||||
|
||||
XtManageChild(frame);
|
||||
XtManageChild(form);
|
||||
|
||||
XtManageChild(rowcol);
|
||||
}
|
||||
|
||||
/******************************************************************\
|
||||
* The buttons at the bottom... *
|
||||
\******************************************************************/
|
||||
|
||||
form = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, 6,
|
||||
NULL );
|
||||
position=0;
|
||||
|
||||
widget = XtVaCreateManagedWidget( "Difference:",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment,XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
NULL );
|
||||
|
||||
recnData->difference =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNeditable, False,
|
||||
XmNmarginHeight, 1,
|
||||
XmNmarginWidth, 1,
|
||||
XmNmaxLength, 10,
|
||||
XmNcolumns, 10,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 6,
|
||||
XmNbottomAttachment,XmATTACH_FORM,
|
||||
XmNbottomOffset, 6,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position++,
|
||||
NULL );
|
||||
|
||||
position++;
|
||||
|
||||
/* The "Ok" button: */
|
||||
widget = XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
recnOkCB, (XtPointer)recnData );
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)(recnData->dialog) );
|
||||
/* The "Cancel" button: */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)(recnData->dialog) );
|
||||
|
||||
/* The "Help" button pops up the reconcile window help page: */
|
||||
widget = XtVaCreateManagedWidget( "Help",
|
||||
xmPushButtonWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
helpMenubarCB, (XtPointer)HMB_RECNWIN );
|
||||
|
||||
/* Fix button area of the pane to its current size, and not let
|
||||
* it resize. */
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
XtManageChild(form);
|
||||
XtManageChild(pane);
|
||||
XtManageChild(recnData->dialog);
|
||||
|
||||
/* now that the matices are set up, fill 'em in with transactions: */
|
||||
recnRefresh(recnData);
|
||||
/* and then refresh the total/difference balance fields: */
|
||||
recnRecalculateBalance(recnData);
|
||||
|
||||
unsetBusyCursor(parent);
|
||||
|
||||
return recnData;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* recnClose *
|
||||
* frees memory allocated for an recnWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - recnData - the data struct for this window *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
recnClose( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
RecnWindow *recnData = (RecnWindow *)cd;
|
||||
Account *acc = recnData->acc;
|
||||
|
||||
_free(recnData);
|
||||
acc->recnData = NULL;
|
||||
|
||||
DEBUG("closed RecnWindow");
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* recnOkCB *
|
||||
* saves account stuff, when the user clicks "Ok" *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - recnData - the data struct for this window *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: data *
|
||||
\********************************************************************/
|
||||
void
|
||||
recnOkCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int nrows,i;
|
||||
Transaction *trans;
|
||||
RecnWindow *recnData = (RecnWindow *)cd;
|
||||
|
||||
/* Update the debit transactions: */
|
||||
XtVaGetValues( recnData->debit, XmNrows, &nrows, NULL );
|
||||
for( i=0; i<nrows; i++ )
|
||||
{
|
||||
String recn = XbaeMatrixGetCell( recnData->debit, i, 0 );
|
||||
if( recn[0] == YREC )
|
||||
{
|
||||
trans = (Transaction *)XbaeMatrixGetRowUserData( recnData->debit, i );
|
||||
trans->reconciled = YREC;
|
||||
/* mark the datafile as needing to be saved: */
|
||||
data->saved = False;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the credit transactions: */
|
||||
XtVaGetValues( recnData->credit, XmNrows, &nrows, NULL );
|
||||
for( i=0; i<nrows; i++ )
|
||||
{
|
||||
String recn = XbaeMatrixGetCell( recnData->credit, i, 0 );
|
||||
if( recn[0] == YREC )
|
||||
{
|
||||
trans = (Transaction *)XbaeMatrixGetRowUserData( recnData->credit, i );
|
||||
trans->reconciled = YREC;
|
||||
/* mark the datafile as needing to be saved: */
|
||||
data->saved = False;
|
||||
}
|
||||
}
|
||||
|
||||
/* refresh the register window */
|
||||
regRefresh(recnData->acc->regData);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* recnCB *
|
||||
* called whenever the users does anything in the debit/credit *
|
||||
* matrices *
|
||||
* *
|
||||
* Args: mw - the matrix widget that called us *
|
||||
* cd - recnData - the data struct for this window *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
recnCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
RecnWindow *recnData = (RecnWindow *)cd;
|
||||
|
||||
XbaeMatrixEnterCellCallbackStruct *cbs =
|
||||
(XbaeMatrixEnterCellCallbackStruct *)cb;
|
||||
int rows = XbaeMatrixNumRows(mw);
|
||||
|
||||
cbs->doit = False;
|
||||
cbs->map = False;
|
||||
|
||||
XbaeMatrixDeselectAll(mw);
|
||||
XbaeMatrixSelectRow( mw, cbs->row );
|
||||
|
||||
/* If we are in the "reconciled" cell, toggle value */
|
||||
if( cbs->column == 0 )
|
||||
{
|
||||
char buf[BUFSIZE];
|
||||
String val = XbaeMatrixGetCell( mw, cbs->row, cbs->column );
|
||||
|
||||
if( val[0] == YREC )
|
||||
{
|
||||
Transaction *trans =
|
||||
(Transaction *)XbaeMatrixGetRowUserData( mw, cbs->row );
|
||||
|
||||
sprintf( buf, "%c", trans->reconciled );
|
||||
XbaeMatrixSetCell( mw, cbs->row, cbs->column, buf );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "%c", YREC );
|
||||
XbaeMatrixSetCell( mw, cbs->row, cbs->column, buf );
|
||||
}
|
||||
|
||||
/* recalculate the total/difference balance fields: */
|
||||
recnRecalculateBalance(recnData);
|
||||
}
|
||||
}
|
1440
src/RegWindow.c
Normal file
1440
src/RegWindow.c
Normal file
File diff suppressed because it is too large
Load Diff
125
src/Reports.c
Normal file
125
src/Reports.c
Normal file
@ -0,0 +1,125 @@
|
||||
/********************************************************************\
|
||||
* Reports.c -- generate an account report window *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/Frame.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
|
||||
#include "Reports.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* simpleReportWindow *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
simpleReportWindow( Widget parent )
|
||||
{
|
||||
Widget dialog, form, frame, rc, widget,
|
||||
label, buttonform;
|
||||
int position; /* ???? */
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* force the size of the dialog so it is not resizable */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNtitle, "Report",
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNwidth, 350,
|
||||
XmNminWidth, 350,
|
||||
XmNmaxWidth, 350,
|
||||
XmNheight, 300,
|
||||
XmNminHeight, 300,
|
||||
XmNmaxHeight, 300,
|
||||
NULL );
|
||||
|
||||
/* The form to put everything in the dialog in */
|
||||
form = XtVaCreateWidget( "form", xmFormWidgetClass, dialog, NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The report type area *
|
||||
\******************************************************************/
|
||||
|
||||
/* Makes a nice looking frame */
|
||||
frame = XtVaCreateManagedWidget( "frame",
|
||||
xmFrameWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, widget,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 20,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 20,
|
||||
NULL);
|
||||
|
||||
|
||||
/******************************************************************\
|
||||
* The buttons at the bottom... *
|
||||
\******************************************************************/
|
||||
|
||||
buttonform = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, form,
|
||||
XmNfractionBase, 5,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, frame,
|
||||
XmNtopOffset, 10,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNbottomOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
position = 1; /* puts the buttons in the right place */
|
||||
|
||||
/* The "Ok" button */
|
||||
widget = XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
XtManageChild(buttonform);
|
||||
|
||||
/******************************************************************/
|
||||
XtManageChild(form);
|
||||
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
505
src/XferWindow.c
Normal file
505
src/XferWindow.c
Normal file
@ -0,0 +1,505 @@
|
||||
/********************************************************************\
|
||||
* XferWindow.c -- the transfer window for xacc (X-Accountant) *
|
||||
* (for transferring between accounts) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/LabelGP.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BuildMenu.h"
|
||||
#include "Account.h"
|
||||
#include "Data.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
typedef struct _menuData
|
||||
{
|
||||
int choice;
|
||||
int *accNum;
|
||||
} MenuData;
|
||||
|
||||
typedef struct _xferwindow
|
||||
{
|
||||
Widget date;
|
||||
Widget desc;
|
||||
Widget amount;
|
||||
Widget memo;
|
||||
int to; /* to and from hold the index of */
|
||||
int from; /* the chosen to/from accounts */
|
||||
int numMenuData;
|
||||
MenuData **menuData;
|
||||
} XferWindow;
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern Data *data;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
void closeXferWindow( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void menuCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
void xferCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* xfewWindow *
|
||||
* opens up a window to do an automatic transfer between accounts *
|
||||
* *
|
||||
* Args: parent - the parent of the window to be created *
|
||||
* Return: none *
|
||||
* Global: data - the accounts, and stuff... *
|
||||
\********************************************************************/
|
||||
void
|
||||
xferWindow( Widget parent )
|
||||
{
|
||||
Date date;
|
||||
char buf[BUFSIZE];
|
||||
Widget dialog, form, widget, label, buttonform, menu;
|
||||
MenuItem *accountMenu;
|
||||
XferWindow *xferData;
|
||||
int position,i;
|
||||
int initial = 0;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
xferData = (XferWindow *)_malloc(sizeof(XferWindow));
|
||||
xferData->to = initial;
|
||||
xferData->from = initial;
|
||||
xferData->menuData = NULL;
|
||||
xferData->numMenuData = 0;
|
||||
|
||||
/* force the size of the dialog so it is not resizable */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNtitle, "Transfer Money",
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNwidth, 450,
|
||||
XmNminWidth, 450,
|
||||
XmNmaxWidth, 450,
|
||||
XmNheight, 230,
|
||||
XmNminHeight, 230,
|
||||
XmNmaxHeight, 230,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( dialog, XmNdestroyCallback,
|
||||
closeXferWindow, (XtPointer)xferData );
|
||||
|
||||
/* The form to put everything in the dialog in */
|
||||
form = XtVaCreateWidget( "form", xmFormWidgetClass, dialog, NULL );
|
||||
/******************************************************************\
|
||||
* Text fields.... *
|
||||
\******************************************************************/
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Date",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 65,
|
||||
NULL );
|
||||
|
||||
todaysDate(&date);
|
||||
sprintf(buf,"%2d/%2d/%4d\0", date.month, date.day, date.year);
|
||||
|
||||
xferData->date =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNvalue, buf,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNtopOffset, 10,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, label,
|
||||
NULL );
|
||||
/* The dateCB ensures that the data that the user enters in
|
||||
* in a valid date format. */
|
||||
XtAddCallback( xferData->date, XmNmodifyVerifyCallback,
|
||||
dateCB, (XtPointer)NULL );
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Description",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->date,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 10,
|
||||
NULL );
|
||||
xferData->desc =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNvalue, "Transfer",
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->date,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, label,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 65,
|
||||
NULL );
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "$",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->date,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 65,
|
||||
NULL );
|
||||
xferData->amount =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->date,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, label,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
XmNrightOffset, 10,
|
||||
NULL );
|
||||
/* The amountCB ensures the data entered in the amount field is
|
||||
* in a valid format */
|
||||
XtAddCallback( xferData->amount, XmNmodifyVerifyCallback,
|
||||
amountCB, (XtPointer)NULL );
|
||||
|
||||
label =
|
||||
XtVaCreateManagedWidget( "Memo",
|
||||
xmLabelGadgetClass, form,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->desc,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 10,
|
||||
NULL );
|
||||
xferData->memo =
|
||||
XtVaCreateManagedWidget( "text",
|
||||
xmTextWidgetClass, form,
|
||||
XmNmaxLength, 40,
|
||||
XmNcolumns, 40,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->desc,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_WIDGET,
|
||||
XmNleftWidget, label,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 65,
|
||||
NULL );
|
||||
|
||||
/******************************************************************\
|
||||
* The popup menus that let the user choose the account to *
|
||||
* transfer to and the account to transfer from *
|
||||
\******************************************************************/
|
||||
accountMenu = (MenuItem *)_malloc((data->numAcc+1)*sizeof(MenuItem));
|
||||
|
||||
/* We have to keep track of the menuData stuff so we can free this
|
||||
* memory when the transfer window is closed... the even slots in
|
||||
* this array are used by the "Frow" menu, and the odd slots are
|
||||
* used by the "To" menu. (The even/odd way was a simple way to
|
||||
* still use i as a index to the array... it makes sense to me,
|
||||
* at least) */
|
||||
xferData->menuData = (MenuData **)_malloc(2*data->numAcc*sizeof(MenuData *));
|
||||
xferData->numMenuData = 2 * data->numAcc;
|
||||
|
||||
for( i=0; i<xferData->numMenuData; i++ )
|
||||
xferData->menuData[i] = NULL;
|
||||
|
||||
for( i=0; i<data->numAcc; i++ )
|
||||
{
|
||||
Account *acc = getAccount( data, i );
|
||||
|
||||
/* This account menu uses the even menuData slots (ie (2*i) ) */
|
||||
xferData->menuData[2*i] = (MenuData *)_malloc(sizeof(MenuData));
|
||||
xferData->menuData[2*i]->choice = i;
|
||||
xferData->menuData[2*i]->accNum = &(xferData->from);
|
||||
|
||||
accountMenu[i].label = acc->accountName;
|
||||
accountMenu[i].wclass = &xmPushButtonWidgetClass;
|
||||
accountMenu[i].mnemonic = 0;
|
||||
accountMenu[i].accelerator = NULL;
|
||||
accountMenu[i].accel_text = NULL;
|
||||
accountMenu[i].callback = menuCB;
|
||||
accountMenu[i].callback_data = xferData->menuData[2*i];
|
||||
accountMenu[i].subitems = (MenuItem *)NULL;
|
||||
}
|
||||
accountMenu[i] .label= NULL;
|
||||
|
||||
widget = BuildMenu( form, XmMENU_OPTION, "From:", 'F',
|
||||
False, initial, accountMenu );
|
||||
|
||||
XtVaSetValues( widget,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->memo,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNleftOffset, 10,
|
||||
NULL );
|
||||
|
||||
XtManageChild(widget);
|
||||
|
||||
for( i=0; i<data->numAcc; i++ )
|
||||
{
|
||||
Account *acc = getAccount( data, i );
|
||||
|
||||
/* This account menu uses the odd menuData slots (ie (2*i)+1 ) */
|
||||
xferData->menuData[2*i+1] = (MenuData *)_malloc(sizeof(MenuData));
|
||||
xferData->menuData[2*i+1]->choice = i;
|
||||
xferData->menuData[2*i+1]->accNum = &(xferData->to);
|
||||
|
||||
accountMenu[i].label = acc->accountName;
|
||||
accountMenu[i].wclass = &xmPushButtonWidgetClass;
|
||||
accountMenu[i].mnemonic = 0;
|
||||
accountMenu[i].accelerator = NULL;
|
||||
accountMenu[i].accel_text = NULL;
|
||||
accountMenu[i].callback = menuCB;
|
||||
accountMenu[i].callback_data = xferData->menuData[2*i+1];
|
||||
accountMenu[i].subitems = (MenuItem *)NULL;
|
||||
}
|
||||
accountMenu[i] .label= NULL;
|
||||
|
||||
widget = BuildMenu( form, XmMENU_OPTION, "To:", 'T',
|
||||
False, initial, accountMenu );
|
||||
|
||||
XtVaSetValues( widget,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, xferData->memo,
|
||||
XmNtopOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 50,
|
||||
NULL );
|
||||
|
||||
XtManageChild(widget);
|
||||
|
||||
_free(accountMenu);
|
||||
|
||||
/******************************************************************\
|
||||
* The buttons at the bottom... *
|
||||
\******************************************************************/
|
||||
|
||||
buttonform = XtVaCreateWidget( "form",
|
||||
xmFormWidgetClass, form,
|
||||
XmNfractionBase, 5,
|
||||
XmNtopAttachment, XmATTACH_WIDGET,
|
||||
XmNtopWidget, widget,
|
||||
XmNtopOffset, 10,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNbottomOffset, 10,
|
||||
XmNleftAttachment, XmATTACH_FORM,
|
||||
XmNrightAttachment, XmATTACH_FORM,
|
||||
NULL );
|
||||
|
||||
position = 1; /* puts the buttons in the right place */
|
||||
|
||||
/* The "Cancel" button */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
/* The "Transfer" button creates the transfer */
|
||||
widget = XtVaCreateManagedWidget( "Transfer",
|
||||
xmPushButtonWidgetClass, buttonform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, position,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, ++position,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
xferCB, (XtPointer)xferData );
|
||||
XtAddCallback( widget, XmNactivateCallback,
|
||||
destroyShellCB, (XtPointer)dialog );
|
||||
|
||||
XtManageChild(buttonform);
|
||||
|
||||
/******************************************************************/
|
||||
XtManageChild(form);
|
||||
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* closeXferWindow *
|
||||
* frees memory allocated for an XferWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - *
|
||||
* cd - xferData - the struct for the XferWindow that is *
|
||||
* being closed *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
closeXferWindow( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
int i;
|
||||
XferWindow *xferData = (XferWindow *)cd;
|
||||
|
||||
for( i=0; i<xferData->numMenuData; i++ )
|
||||
_free(xferData->menuData[i]);
|
||||
|
||||
_free(xferData->menuData);
|
||||
|
||||
_free(xferData);
|
||||
|
||||
DEBUG("close XferWindow");
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* menuCB -- keeps track of the to and from menues *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - menuData - has the menu choice and a pointer to *
|
||||
* either the to of from fields in XferWindow *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
menuCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
MenuData *menuData = (MenuData *)cd;
|
||||
|
||||
*(menuData->accNum) = menuData->choice;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* xferCB -- creates the transfer between accounts *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - xferData - the struct of data associated with *
|
||||
* the XfewWindow *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
* Global: data - the data from the datafile *
|
||||
\********************************************************************/
|
||||
void
|
||||
xferCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XferWindow *xferData = (XferWindow *)cd;
|
||||
Transaction *toTrans, *fromTrans;
|
||||
Account *acc;
|
||||
String str;
|
||||
int dollar=0,cent=0,pos=0;
|
||||
|
||||
data->saved = False;
|
||||
|
||||
/* "toTrans" is the transfer transaction that goes into the to account,
|
||||
* and "fromTrans" goes into the from account */
|
||||
toTrans = (Transaction *)_malloc(sizeof(Transaction));
|
||||
fromTrans = (Transaction *)_malloc(sizeof(Transaction));
|
||||
|
||||
/* Create the "toTrans" transaction */
|
||||
str = XmTextGetString(xferData->date);
|
||||
todaysDate(&(toTrans->date));
|
||||
sscanf( str, "%d/%d/%d", &(toTrans->date.month),
|
||||
&(toTrans->date.day), &(toTrans->date.year) );
|
||||
str = XmTextGetString(xferData->amount);
|
||||
sscanf( str, "%d.%2d", &dollar, ¢ );
|
||||
toTrans->amount = 100*dollar + cent;
|
||||
toTrans->num = XtNewString("");
|
||||
|
||||
/* Get the memo, and add the "from" account name to it */
|
||||
{
|
||||
String memo = NULL;
|
||||
/* Note, don't use _malloc/_free here, because otherwise it
|
||||
* would mess up the memory accounting if memory debugging
|
||||
* is turned on */
|
||||
acc = getAccount(data,xferData->from);
|
||||
str = XmTextGetString(xferData->memo);
|
||||
memo = (String)malloc(strlen(str)+
|
||||
strlen(acc->accountName)+
|
||||
strlen("[From: ] ") );
|
||||
sprintf( memo, "[From: %s] %s\0", acc->accountName, str );
|
||||
toTrans->memo = memo;
|
||||
free(str);
|
||||
}
|
||||
|
||||
toTrans->description = XmTextGetString(xferData->desc);
|
||||
toTrans->catagory = 0;
|
||||
toTrans->reconciled = NREC;
|
||||
|
||||
acc = getAccount(data,xferData->to);
|
||||
pos = insertTransaction( acc, toTrans );
|
||||
|
||||
/* Refresh the "to" account register window */
|
||||
regRefresh(acc->regData);
|
||||
/* Refresh the "to" account reconcile window */
|
||||
recnRefresh(acc->recnData);
|
||||
|
||||
/* Create the "fromTrans" transaction */
|
||||
str = XmTextGetString(xferData->date);
|
||||
todaysDate(&(fromTrans->date));
|
||||
sscanf( str, "%d/%d/%d", &(fromTrans->date.month),
|
||||
&(fromTrans->date.day), &(fromTrans->date.year) );
|
||||
fromTrans->amount = -1*toTrans->amount;
|
||||
fromTrans->num = XtNewString("");
|
||||
|
||||
/* Get the memo, and add the "to" account name to it */
|
||||
{
|
||||
String memo = NULL;
|
||||
/* Note, don't use _malloc/_free here, because otherwise it
|
||||
* would mess up the memory accounting if memory debugging
|
||||
* is turned on */
|
||||
acc = getAccount(data,xferData->to);
|
||||
str = XmTextGetString(xferData->memo);
|
||||
memo = (String)malloc(strlen(str)+
|
||||
strlen(acc->accountName)+
|
||||
strlen("[To: ] ") );
|
||||
sprintf( memo, "[To: %s] %s\0", acc->accountName, str );
|
||||
fromTrans->memo = memo;
|
||||
free(str);
|
||||
}
|
||||
|
||||
fromTrans->description = XmTextGetString(xferData->desc);
|
||||
fromTrans->catagory = 0;
|
||||
fromTrans->reconciled = NREC;
|
||||
|
||||
acc = getAccount(data,xferData->from);
|
||||
pos = insertTransaction( acc, fromTrans );
|
||||
|
||||
/* Refresh the "from" account register window */
|
||||
regRefresh(acc->regData);
|
||||
/* Refresh the "from" account reconcile window */
|
||||
recnRefresh(acc->recnData);
|
||||
|
||||
refreshMainWindow();
|
||||
}
|
185
src/date.c
Normal file
185
src/date.c
Normal file
@ -0,0 +1,185 @@
|
||||
/********************************************************************\
|
||||
* date.c -- utility functions to handle the date (adjusting, get *
|
||||
* current date, etc.) for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
* *
|
||||
* *
|
||||
* TODO: - for now, every year is leap year *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#include <time.h>
|
||||
#include "date.h"
|
||||
#include "util.h"
|
||||
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
int validateDate( Date *date );
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
char days[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 };
|
||||
|
||||
/********************************************************************\
|
||||
* adjustDay *
|
||||
* adds adj to the current day of the month... the resulting day *
|
||||
* of the month is a valid day of the month *
|
||||
* *
|
||||
* Args: date - the date structure to edit *
|
||||
* adj - the amount to adjust the day of the month by *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
adjustDay( Date *date, int adj )
|
||||
{
|
||||
date->day += adj;
|
||||
validateDate(date);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* adjustMonth *
|
||||
* adds adj to the current month of the year.. the resulting *
|
||||
* month of the year is corrected to be in the range [1..12], *
|
||||
* incrementing/decrementing the year if necessary. *
|
||||
* *
|
||||
* Args: date - the date structure to edit *
|
||||
* adj - the amount to adjust the day of the month by *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
adjustMonth( Date *date, int adj )
|
||||
{
|
||||
date->month += adj;
|
||||
validateDate(date);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* validateDate *
|
||||
* ensures that all the fields in date are in the valid range *
|
||||
* (ie month = [1..12], day is not less than 1, and not greater *
|
||||
* than last day of the month.). If fields are not in the valid *
|
||||
* range, they are adjusted. *
|
||||
* *
|
||||
* Args: date - the date structure to edit *
|
||||
* Return: True if date was changed, otherwise False *
|
||||
\********************************************************************/
|
||||
int
|
||||
validateDate( Date *date )
|
||||
{
|
||||
int valid = True;
|
||||
|
||||
/* the "% 12" business is because month might not be valid!*/
|
||||
while( date->day > days[(date->month+11) % 12] )
|
||||
{
|
||||
valid = False;
|
||||
date->day -= days[(date->month+11) % 12];
|
||||
date->month++;
|
||||
}
|
||||
while( date->day < 1 )
|
||||
{
|
||||
valid = False;
|
||||
date->month--;
|
||||
date->day += days[(date->month+11) % 12];
|
||||
}
|
||||
while( date->month > 12 )
|
||||
{
|
||||
valid = False;
|
||||
date->month -= 12;
|
||||
date->year++;
|
||||
}
|
||||
while( date->month < 1 )
|
||||
{
|
||||
valid = False;
|
||||
date->month += 12;
|
||||
date->year--;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* todaysDate *
|
||||
* takes a (Date *) and fills it in with today's date *
|
||||
* *
|
||||
* Args: date - the struct to be filled in *
|
||||
* Return: today's date *
|
||||
\********************************************************************/
|
||||
Date*
|
||||
todaysDate( Date *date )
|
||||
{
|
||||
time_t t;
|
||||
struct tm *theTime;
|
||||
|
||||
time(&t);
|
||||
theTime = localtime(&t);
|
||||
|
||||
date->day = theTime->tm_mday;
|
||||
date->month = theTime->tm_mon + 1;
|
||||
date->year = theTime->tm_year + 1900;
|
||||
|
||||
// _free(theTime);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* daysInMonth *
|
||||
* returns the number of days in month *
|
||||
* *
|
||||
* Args: month - the current month *
|
||||
* Return: the number of days in month *
|
||||
\********************************************************************/
|
||||
int
|
||||
daysInMonth( int month )
|
||||
{
|
||||
return days[month-1];
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* datecmp *
|
||||
* compares date1 and date2 *
|
||||
* *
|
||||
* Args: date1 - the first date to look at *
|
||||
* date2 - the second date in the comparison *
|
||||
* Return: < 0 if date1<date2, == 0 if date1==date2, > 0 otherwise *
|
||||
\********************************************************************/
|
||||
int
|
||||
datecmp( Date *date1, Date *date2 )
|
||||
{
|
||||
if( date1 == NULL )
|
||||
return 0;
|
||||
else if( date2 == NULL )
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
unsigned int d1 = date1->day + (31 * date1->month) + (365 * date1->year);
|
||||
unsigned int d2 = date2->day + (31 * date2->month) + (365 * date2->year);
|
||||
|
||||
if( d1 < d2 )
|
||||
return -1;
|
||||
if( d1 == d2 )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
156
src/main.c
Normal file
156
src/main.c
Normal file
@ -0,0 +1,156 @@
|
||||
/********************************************************************\
|
||||
* main.c -- main for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include "BuildMenu.h"
|
||||
#include "RegWindow.h"
|
||||
#include "FileIO.h"
|
||||
#include "FileBox.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
Data *data = NULL;
|
||||
char *datafile;
|
||||
Widget toplevel;
|
||||
Boolean realized=False; /* Has the toplevel been realized? */
|
||||
XtAppContext app;
|
||||
|
||||
/* The names of the different types of accounts. For resource
|
||||
* specification */
|
||||
String accRes[] ={
|
||||
"bank",
|
||||
"cash",
|
||||
"asset",
|
||||
"credit",
|
||||
"liability",
|
||||
"portfolio",
|
||||
"mutual"
|
||||
};
|
||||
|
||||
/** FALLBACK RESOURCES **********************************************/
|
||||
/* NOTE: These will eventually be moved out into a site-default file,
|
||||
* but default-resources are here for now, for convenience */
|
||||
String fbRes[] = {
|
||||
"*fontList: -*-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
|
||||
"*Background: grey",
|
||||
"*text.fontList: -*-helvetica-medium-r-normal--*-100-*-*-*-*-*-*",
|
||||
/* Help stuff" */
|
||||
"*help*geometry: 530x480-0-0",
|
||||
/* "*help*View*Background: #ffffff", */
|
||||
/* MenuBar stuff: */
|
||||
"*menubar*marginHeight: 1",
|
||||
"*menubar*marginWidth: 1",
|
||||
/* Register window account type specific stuff: */
|
||||
"*regbank.oddRowBackground: #ffffaa",
|
||||
"*regcash.oddRowBackground: #ccffcc",
|
||||
"*regasset.oddRowBackground: #ccffcc",
|
||||
"*regcredit.oddRowBackground: #ccccff",
|
||||
"*regliability.oddRowBackground: #ffcccc",
|
||||
"*regportfolio.oddRowBackground: grey",
|
||||
"*regmutual.oddRowBackground: grey",
|
||||
"*regportfolio.evenRowBackground:grey",
|
||||
"*regmutual.evenRowBackground: grey",
|
||||
/* Other register window account stuff: */
|
||||
"*reg*fontList: -*-helvetica-medium-r-normal--*-100-*-*-*-*-*-*",
|
||||
"*reg*evenRowBackground: white",
|
||||
"*reg*shadowType: SHADOW_IN",
|
||||
"*reg*shadowThickness: 1",
|
||||
"*reg*cellShadowThickness: 1",
|
||||
"*reg*cellShadowType: SHADOW_IN",
|
||||
"*reg*cellMarginWidth: 1",
|
||||
"*reg*cellMarginHeight: 0",
|
||||
/* Reconcile window matrices stuff: */
|
||||
"*recn*fontList: -*-helvetica-medium-r-normal--*-100-*-*-*-*-*-*",
|
||||
"*recn*.oddRowBackground: white",
|
||||
"*recn*.evenRowBackground: white",
|
||||
"*recn*shadowType: SHADOW_ETCHED_IN",
|
||||
"*recn*shadowThickness: 1",
|
||||
"*recn*cellShadowThickness: 1",
|
||||
"*recn*cellShadowType: SHADOW_ETCHED_IN",
|
||||
"*recn*cellMarginWidth: 0",
|
||||
"*recn*cellMarginHeight: 0",
|
||||
NULL,
|
||||
};
|
||||
|
||||
/********************************************************************\
|
||||
* main *
|
||||
* the entry point for the program... sets up the top level widget *
|
||||
* and calls the mainWindow() function which creates the main *
|
||||
* window. *
|
||||
* *
|
||||
* Args: argc, the number of command line arguments, and argv, *
|
||||
* the array of command line args *
|
||||
* Return: *
|
||||
* Global: data - the data from the datafile *
|
||||
* datafile - the name of the user's datafile *
|
||||
* toplevel - the toplevel widget, for creating new windows *
|
||||
* app - the XtAppContext *
|
||||
\********************************************************************/
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
#ifdef DEBUGMEMORY
|
||||
char *blk;
|
||||
DEBUG("Initializing memory");
|
||||
blk = (char *)_malloc(8192);
|
||||
_free(blk);
|
||||
printf(" coresize = %d\n",_coresize());
|
||||
DEBUG("Done initializing memory");
|
||||
#endif
|
||||
data = NULL;
|
||||
|
||||
toplevel = XtVaAppInitialize( &app, "Xacc", NULL, 0,
|
||||
&argc, argv, fbRes,
|
||||
NULL );
|
||||
|
||||
/* read in the filename (should be the first arg after all
|
||||
* the X11 stuff */
|
||||
if( argc > 1 )
|
||||
datafile = argv[1];
|
||||
else
|
||||
datafile = fileBox( toplevel, OPEN );
|
||||
|
||||
if( datafile != NULL )
|
||||
data = readData(datafile); /* load the accounts data from datafile*/
|
||||
|
||||
if( data == NULL )
|
||||
{
|
||||
data = mallocData(); /* the file could not be found */
|
||||
data->new = True;
|
||||
}
|
||||
|
||||
/* Make main window */
|
||||
mainWindow(toplevel);
|
||||
|
||||
/* Draw toplevel */
|
||||
XtRealizeWidget(toplevel);
|
||||
realized = TRUE;
|
||||
|
||||
/* Enter event loop */
|
||||
XtAppMainLoop(app);
|
||||
}
|
||||
|
580
src/util.c
Normal file
580
src/util.c
Normal file
@ -0,0 +1,580 @@
|
||||
/********************************************************************\
|
||||
* util.c -- utility functions that are used everywhere else for *
|
||||
* xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License*
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* Author: Rob Clark *
|
||||
* Internet: rclark@cs.hmc.edu *
|
||||
* Address: 609 8th Street *
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/Text.h>
|
||||
#include <Xm/PanedW.h>
|
||||
#include <Xm/Form.h>
|
||||
#include <Xm/PushB.h>
|
||||
#include <Xm/DialogS.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/MessageB.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
extern XtAppContext app;
|
||||
extern int realized;
|
||||
|
||||
/********************************************************************\
|
||||
* DEBUGGING MEMORY ALLOCATION STUFF *
|
||||
\********************************************************************/
|
||||
#ifdef DEBUGMEMORY
|
||||
size_t core=0;
|
||||
void
|
||||
dfree( void *ptr )
|
||||
{
|
||||
core -= malloc_usable_size(ptr);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void*
|
||||
dmalloc( size_t size )
|
||||
{
|
||||
char *ptr = (char *)malloc(size);
|
||||
int i;
|
||||
for( i=0; i<size; i++ )
|
||||
ptr[i] = '.';
|
||||
|
||||
core += malloc_usable_size(ptr);
|
||||
return (void *)ptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
dcoresize(void)
|
||||
{
|
||||
return core;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************\
|
||||
* dateCB -- ensures the data the user enters in the date field *
|
||||
* is in a valid format. *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - the callback struct *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
dateCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)cb;
|
||||
char input;
|
||||
|
||||
/* TODO: ??? add support for date field accelerator keys!! */
|
||||
if( cbs->text->ptr != NULL )
|
||||
{
|
||||
input = (cbs->text->ptr)[0];
|
||||
|
||||
switch( input )
|
||||
{
|
||||
case '/':
|
||||
/* Make sure that there is at most two '/' */
|
||||
{
|
||||
String str = XmTextGetString(mw);
|
||||
int i,count=0;
|
||||
|
||||
for( i=0; str[i] != '\0'; i++ )
|
||||
if( str[i] == '/' )
|
||||
count++;
|
||||
if( count >= 2 )
|
||||
cbs->doit = False;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* only accept the input if it is a number */
|
||||
cbs->doit = isNum(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* amountCB -- ensures the data entered in the amount field is in *
|
||||
* a valid format. *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - the callback struct *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
amountCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)cb;
|
||||
char input;
|
||||
|
||||
if( cbs->text->ptr != NULL )
|
||||
{
|
||||
input = (cbs->text->ptr)[0];
|
||||
|
||||
switch( input )
|
||||
{
|
||||
case '.':
|
||||
/* Make sure that there is only one '.' */
|
||||
{
|
||||
String str = XmTextGetString(mw);
|
||||
int i,count=0;
|
||||
|
||||
for( i=0; str[i] != '\0'; i++ )
|
||||
if( str[i] == '.' )
|
||||
count++;
|
||||
if( count >= 1 )
|
||||
cbs->doit = False;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* only accept the input if it is a number */
|
||||
cbs->doit = isNum(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* noeditCB *
|
||||
* makes an Xbae matrix non-editable *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
noeditCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XbaeMatrixEnterCellCallbackStruct *cbs =
|
||||
(XbaeMatrixEnterCellCallbackStruct * )cb;
|
||||
|
||||
cbs->doit = False;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* destroyShellCB *
|
||||
* a callback to destroy a widget (cd, not w, because we want to *
|
||||
* destroy a window, not a button!) *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - the widget to destroy *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
destroyShellCB( Widget w, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
Widget window = (Widget)cd;
|
||||
|
||||
XtDestroyWidget(window);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* setBusyCursor *
|
||||
* sets the cursor to the busy watch *
|
||||
* *
|
||||
* Args: w - the widget over which to make cursor busy *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
setBusyCursor( Widget w )
|
||||
{
|
||||
if( realized )
|
||||
{
|
||||
static Cursor watch = 0;
|
||||
|
||||
if( watch == 0 )
|
||||
watch = XCreateFontCursor(XtDisplay(w),XC_watch);
|
||||
|
||||
XDefineCursor(XtDisplay(w),XtWindow(w),watch);
|
||||
XmUpdateDisplay(w);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* unsetBusyCursor *
|
||||
* sets the cursor to the default cursor *
|
||||
* *
|
||||
* Args: w - the widget over which to make cursor normal *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
unsetBusyCursor( Widget w )
|
||||
{
|
||||
if( realized )
|
||||
{
|
||||
XUndefineCursor(XtDisplay(w),XtWindow(w));
|
||||
XmUpdateDisplay(w);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
**************** TEXTBOX STUFF *************************************
|
||||
\********************************************************************/
|
||||
typedef struct _textbox {
|
||||
Widget textfield;
|
||||
char *text;
|
||||
} TextBox;
|
||||
|
||||
void textBoxCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* textBox *
|
||||
* opens up a text box, and displays text *
|
||||
* *
|
||||
* NOTE: This function does not return until the textBox is closed *
|
||||
* *
|
||||
* Args: parent - the parent widget *
|
||||
* title - the title of the window *
|
||||
* text - the initial text to display *
|
||||
* editable - can this text be edited by the user? *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
char *
|
||||
textBox( Widget parent, char *title, char *text, Boolean editable )
|
||||
{
|
||||
Widget dialog,
|
||||
pane,
|
||||
controlform,
|
||||
actionform,
|
||||
widget;
|
||||
Arg args[10];
|
||||
TextBox *textData = (TextBox *)_malloc(sizeof(TextBox));
|
||||
textData->text = NULL;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* Create the dialog box... XmNdeleteResponse is set to
|
||||
* XmDESTROY so the dialog's memory is freed when it is closed */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNdialogStyle, XmDIALOG_APPLICATION_MODAL,
|
||||
XmNtitle, title,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
XmNminWidth, 150,
|
||||
XmNminHeight, 200,
|
||||
NULL );
|
||||
|
||||
/* Create a PanedWindow Manager for the dialog box... the child
|
||||
* of optiondialog the paned window is the parent of the two
|
||||
* forms which comprise the two areas of the dialog box...
|
||||
* The sash is set to minimun size to make it invisible */
|
||||
pane = XtVaCreateWidget( "pane",
|
||||
xmPanedWindowWidgetClass, dialog,
|
||||
XmNsashWidth, 1,
|
||||
XmNsashHeight, 1,
|
||||
XmNtraversalOn, False,
|
||||
NULL );
|
||||
|
||||
/** CONTROLFORM ****************************************
|
||||
* Create a controlform for control area of dialog box */
|
||||
controlform = XtVaCreateWidget( "controlform",
|
||||
xmFormWidgetClass, pane,
|
||||
NULL );
|
||||
|
||||
/* Create a text widget as child of controlform */
|
||||
XtSetArg( args[0], XmNeditMode, XmMULTI_LINE_EDIT );
|
||||
XtSetArg( args[1], XmNwordWrap, True );
|
||||
XtSetArg( args[2], XmNrows, 12 );
|
||||
XtSetArg( args[3], XmNcolumns, 70 );
|
||||
XtSetArg( args[4], XmNeditable, editable );
|
||||
XtSetArg( args[5], XmNscrollHorizontal, False );
|
||||
XtSetArg( args[6], XmNtopAttachment, XmATTACH_FORM );
|
||||
XtSetArg( args[7], XmNbottomAttachment, XmATTACH_FORM );
|
||||
XtSetArg( args[8], XmNleftAttachment, XmATTACH_FORM );
|
||||
XtSetArg( args[9], XmNrightAttachment, XmATTACH_FORM );
|
||||
|
||||
textData->textfield =
|
||||
XmCreateScrolledText( controlform, "text", args, 10 );
|
||||
|
||||
XtManageChild( textData->textfield );
|
||||
|
||||
XmTextSetString( textData->textfield, text );
|
||||
|
||||
XtManageChild( controlform );
|
||||
|
||||
/** ACTIONFORM ********************************************
|
||||
* Create a Form actionform for action area of dialog box */
|
||||
{
|
||||
int fb = editable ? 5 : 3;
|
||||
actionform = XtVaCreateWidget( "actionform",
|
||||
xmFormWidgetClass, pane,
|
||||
XmNfractionBase, fb,
|
||||
NULL );
|
||||
}
|
||||
/* The OK button is anchored to the form, between divider 1 & 2
|
||||
* (in the fraction base) */
|
||||
widget = XtVaCreateManagedWidget( "Ok",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 1,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 2,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
/* Add callback function to Ok.. calls textBoxCB to save the text,
|
||||
* and destroyOptionDialog to kill option dialog box */
|
||||
XtAddCallback( widget, XmNactivateCallback, textBoxCB, textData );
|
||||
XtAddCallback( widget, XmNactivateCallback, destroyShellCB, dialog );
|
||||
|
||||
if( editable )
|
||||
{
|
||||
/* If it is editable, provide a cancel button too! */
|
||||
widget = XtVaCreateManagedWidget( "Cancel",
|
||||
xmPushButtonWidgetClass, actionform,
|
||||
XmNtopAttachment, XmATTACH_FORM,
|
||||
XmNbottomAttachment, XmATTACH_FORM,
|
||||
XmNleftAttachment, XmATTACH_POSITION,
|
||||
XmNleftPosition, 3,
|
||||
XmNrightAttachment, XmATTACH_POSITION,
|
||||
XmNrightPosition, 4,
|
||||
XmNshowAsDefault, True,
|
||||
NULL );
|
||||
|
||||
/* Add callback function to Cancel.. calls destroyOptionDialog to
|
||||
* kill option dialog box */
|
||||
XtAddCallback( widget, XmNactivateCallback, destroyShellCB, dialog );
|
||||
}
|
||||
|
||||
/* Fix action area of the pane to its current size, and not let it
|
||||
* resize. */
|
||||
XtManageChild( actionform );
|
||||
|
||||
{
|
||||
Dimension h;
|
||||
XtVaGetValues( widget, XmNheight, &h, NULL );
|
||||
XtVaSetValues( actionform, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL );
|
||||
}
|
||||
|
||||
XtManageChild( pane );
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
|
||||
/* while the user hasn't pushed "Ok", simulate XtMainLoop.
|
||||
* When textData->text changes from NULL, it means the user
|
||||
* has pressed "Ok". Don't break loop until XtAppPending()
|
||||
* also returns False to assure widget destruction. */
|
||||
while( textData->text == NULL || XtAppPending(app) )
|
||||
XtAppProcessEvent( app, XtIMAll );
|
||||
|
||||
return textData->text;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* textBoxCB *
|
||||
* callback that saves the data in the the buffer before textBox *
|
||||
* can return *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - textData *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
textBoxCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
TextBox *textData = (TextBox *)cd;
|
||||
|
||||
textData->text = XmTextGetString( textData->textfield );
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
*********************************************************************
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
**************** VERIFYBOX STUFF ***********************************
|
||||
\********************************************************************/
|
||||
typedef struct _verifybox {
|
||||
Boolean done;
|
||||
Boolean answer;
|
||||
} VerifyBox;
|
||||
|
||||
void verifyBoxCB( Widget mw, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* verifyBox *
|
||||
* display a message, and asks the user to press "Ok" or "Cancel" *
|
||||
* *
|
||||
* NOTE: This function does not return until the dialog is closed *
|
||||
* *
|
||||
* Args: parent - the parent widget *
|
||||
* title - the title of the window *
|
||||
* text - the message to display *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
Boolean
|
||||
verifyBox( Widget parent, char *text )
|
||||
{
|
||||
Widget dialog,msgbox;
|
||||
XmString message = XmStringCreateSimple(text);
|
||||
XmString yes,no;
|
||||
VerifyBox verifyData;
|
||||
|
||||
verifyData.done = False;
|
||||
verifyData.answer = False;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* Create the dialog box... XmNdeleteResponse is set to
|
||||
* XmDESTROY so the dialog's memory is freed when it is closed */
|
||||
dialog = XtVaCreatePopupShell( "dialog",
|
||||
xmDialogShellWidgetClass, parent,
|
||||
XmNdialogStyle, XmDIALOG_APPLICATION_MODAL,
|
||||
XmNtitle, "",
|
||||
XmNwidth, 300,
|
||||
XmNdeleteResponse, XmDESTROY,
|
||||
NULL );
|
||||
|
||||
yes = XmStringCreateSimple(" Yes ");
|
||||
no = XmStringCreateSimple(" No ");
|
||||
|
||||
/* Create a messagebox.... has message and "Ok","Cancel" buttons */
|
||||
msgbox =
|
||||
XtVaCreateManagedWidget( "dialog",
|
||||
xmMessageBoxWidgetClass, dialog,
|
||||
XmNdialogType, XmDIALOG_QUESTION,
|
||||
XmNdefaultButtonType,XmDIALOG_CANCEL_BUTTON,
|
||||
XmNmessageString, message,
|
||||
XmNcancelLabelString,no,
|
||||
XmNokLabelString, yes,
|
||||
NULL );
|
||||
|
||||
/* Get rid of the "Help" Button!! */
|
||||
XtUnmanageChild( XmMessageBoxGetChild(msgbox, XmDIALOG_HELP_BUTTON) );
|
||||
|
||||
/* We can make verifyData an automatic variable, and pass it by
|
||||
* reference because this function doesn't return until the
|
||||
* dialog is destroyed, which means that the callbacks are done */
|
||||
XtAddCallback( msgbox, XmNokCallback, verifyBoxCB, &verifyData );
|
||||
XtAddCallback( msgbox, XmNcancelCallback, verifyBoxCB, &verifyData );
|
||||
|
||||
XtPopup( dialog, XtGrabNone );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
|
||||
/* while the user hasn't pushed "Ok" or "Cancel", simulate XtMainLoop.
|
||||
* When verifyData.done changes from False, it means the user has
|
||||
* pressed a button. Don't break loop until XtAppPending() also
|
||||
* returns False to assure widget destruction. */
|
||||
while( !(verifyData.done) || XtAppPending(app) )
|
||||
XtAppProcessEvent( app, XtIMAll );
|
||||
|
||||
XmStringFree(message);
|
||||
XmStringFree(yes);
|
||||
XmStringFree(no);
|
||||
|
||||
return verifyData.answer;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* verifyBoxCB *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - verifyData *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
verifyBoxCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)cb;
|
||||
VerifyBox *verifyData = (VerifyBox *)cd;
|
||||
|
||||
switch( cbs->reason )
|
||||
{
|
||||
case XmCR_OK:
|
||||
verifyData->answer = True;
|
||||
break;
|
||||
case XmCR_CANCEL:
|
||||
default:
|
||||
verifyData->answer = False;
|
||||
}
|
||||
|
||||
verifyData->done = True;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
*********************************************************************
|
||||
\********************************************************************/
|
||||
|
||||
/********************************************************************\
|
||||
* errorBox *
|
||||
* displays an error dialog box *
|
||||
* *
|
||||
* Args: w - the parent widget *
|
||||
* message - the error message to display *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
void
|
||||
errorBox( Widget parent, char *message )
|
||||
{
|
||||
Widget dialog,
|
||||
pane,
|
||||
controlform,
|
||||
actionform,
|
||||
widget;
|
||||
|
||||
if( message != NULL )
|
||||
{
|
||||
XmString warning_msg,
|
||||
dialogname;
|
||||
|
||||
setBusyCursor( parent );
|
||||
|
||||
/* Create a warning dialog */
|
||||
dialog = XmCreateWarningDialog( parent, "warning", NULL, 0 );
|
||||
|
||||
/* Create the warning XmString */
|
||||
warning_msg = XmStringCreateLtoR( message, charset );
|
||||
dialogname = XmStringCreateSimple( "WARNING" );
|
||||
XtVaSetValues( dialog,
|
||||
XmNdialogTitle, dialogname,
|
||||
XmNmessageString, warning_msg,
|
||||
NULL );
|
||||
|
||||
/* Get rid of the "Help" and "Cancel" buttons that would normally
|
||||
* be in the warning dialog dialog by unmanaging them */
|
||||
XtUnmanageChild( XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON) );
|
||||
XtUnmanageChild( XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON) );
|
||||
|
||||
/* Register the callback for the "Ok" button */
|
||||
XtAddCallback( dialog, XmNokCallback, destroyShellCB, dialog );
|
||||
|
||||
/* Free up the allocated XmStrings */
|
||||
XmStringFree( warning_msg );
|
||||
XmStringFree( dialogname );
|
||||
|
||||
XtManageChild( dialog );
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user