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