mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge in changes for in-line transfer between accounts
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@53 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
f4b8273650
commit
a9d8972674
1
Makefile
1
Makefile
@ -47,6 +47,7 @@ CFLAGS = $(LFLAGS) -I../include -I../libhtmlw -I../Xbae-4.6.2-linas \
|
||||
# -DUSEQUICKFILL # -DUSE_NO_COLOR -DDEBUGMEMORY -DUSEDEBUG
|
||||
LFLAGS = -g -L/usr/local/lib -L/usr/X11/lib -L../lib
|
||||
LIBS = -lXm -lXmu -lXt -lXpm -lXext -lSM -lICE -lX11
|
||||
# LIBS = -lXm -lXmu -lXt -lXpm -lXext -lSM -lICE -lX11 -lefence
|
||||
|
||||
######################################################################
|
||||
|
||||
|
6
README
6
README
@ -39,11 +39,15 @@ sorry, no "make install" yet.
|
||||
|
||||
Status:
|
||||
-------
|
||||
As of version 0.9j:
|
||||
As of version 0.9k:
|
||||
Bugs:
|
||||
-- Cash distributions & cash dividends on stock not handled properly
|
||||
-- tabbing between fields for mutual funds does not work correctly.
|
||||
-- should add "number of shares" to transfer popup when transferring
|
||||
from bank account to portfolio.
|
||||
-- Nasty core dump in motif when two register windows are opened,
|
||||
and then closed. Beats the heck out of me.
|
||||
|
||||
|
||||
---------------
|
||||
Bare-bones Mutual Fund and Stock Portfolio handling
|
||||
|
@ -662,12 +662,12 @@ Do you want to continue anyway?\n");
|
||||
|
||||
/* Add an opening balance transaction (as the first transaction) */
|
||||
trans = mallocTransaction();
|
||||
initTransaction(trans);
|
||||
|
||||
todaysDate( &(trans->date) );
|
||||
trans->num = XtNewString("");
|
||||
trans->description = XtNewString("Opening Balance\0");
|
||||
trans->memo = XtNewString("");
|
||||
|
||||
XtFree (trans->description);
|
||||
trans->description = XtNewString("Opening Balance");
|
||||
|
||||
/* add the new transaction to the account */
|
||||
insertTransaction( acc, trans );
|
||||
|
||||
|
190
src/Account.c
190
src/Account.c
@ -23,11 +23,11 @@
|
||||
* Huntington Beach, CA 92648-4632 *
|
||||
\********************************************************************/
|
||||
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "Data.h"
|
||||
#include "Account.h"
|
||||
#include "Data.h"
|
||||
#include "date.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
extern Data *data;
|
||||
int next_free_unique_account_id = 0;
|
||||
@ -94,13 +94,14 @@ freeAccount( Account *acc )
|
||||
|
||||
/* free the transaction only if its not
|
||||
* a part of a double entry */
|
||||
if (trans->credit == _acc) trans->credit = NULL;
|
||||
if (trans->debit == _acc) trans->debit = NULL;
|
||||
if (_acc == trans->credit) trans->credit = NULL;
|
||||
if (_acc == trans->debit) trans->debit = NULL;
|
||||
if ( (NULL == trans->debit) && (NULL == trans->credit) ) {
|
||||
freeTransaction( trans );
|
||||
}
|
||||
}
|
||||
|
||||
/* free the array of pointers */
|
||||
_free( acc->transaction );
|
||||
|
||||
_free(acc);
|
||||
@ -142,7 +143,6 @@ removeTransaction( Account *acc, int num )
|
||||
if( acc != NULL )
|
||||
{
|
||||
int i,j;
|
||||
struct _account * _acc = (struct _account *) acc;
|
||||
Transaction **oldTrans = acc->transaction;
|
||||
|
||||
/* check for valid number */
|
||||
@ -173,104 +173,138 @@ removeTransaction( Account *acc, int num )
|
||||
|
||||
/* if this is a double-entry transaction, be sure to
|
||||
* unmark it. */
|
||||
if (trans->credit == _acc) trans->credit = NULL;
|
||||
if (trans->debit == _acc) trans->debit = NULL;
|
||||
if (((Account *)trans->credit) == acc) trans->credit = NULL;
|
||||
if (((Account *)trans->debit) == acc) trans->debit = NULL;
|
||||
|
||||
}
|
||||
return trans;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccRemoveTransaction( Account *acc, Transaction *trans)
|
||||
{
|
||||
int i = getNumOfTransaction (acc, trans);
|
||||
if (0 <= i) {
|
||||
removeTransaction (acc, i);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
int
|
||||
insertTransaction( Account *acc, Transaction *trans )
|
||||
{
|
||||
int position=-1;
|
||||
int i,j;
|
||||
Date *dj,*dt;
|
||||
int inserted = False;
|
||||
Transaction **oldTrans;
|
||||
|
||||
if( acc != NULL )
|
||||
if (NULL == acc) {
|
||||
printf ("Internal Error: insertTransaction(): \n");
|
||||
printf (" no account specified ! \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the transaction hasn't already been marked as a debit
|
||||
* or a credit to this account, then provide a default
|
||||
* behavior for double-entry insertion.
|
||||
*
|
||||
* If this appears to be a new transaction, then default
|
||||
* it to being a credit. If this transaction is already
|
||||
* in another account, assume this is the other half.
|
||||
*/
|
||||
|
||||
if ( (acc != (Account *) trans->credit) &&
|
||||
(acc != (Account *) trans->debit) ) {
|
||||
|
||||
if (NULL == trans->credit) {
|
||||
trans->credit = (struct _account *) acc;
|
||||
} else
|
||||
if (NULL == trans->debit) {
|
||||
trans->debit = (struct _account *) acc;
|
||||
} else
|
||||
{
|
||||
int i,j;
|
||||
Date *dj,*dt;
|
||||
int inserted = False;
|
||||
struct _account * _acc = (struct _account *) acc;
|
||||
Transaction **oldTrans = acc->transaction;
|
||||
|
||||
/* provide a default behavior for double-entry insertion */
|
||||
/* If this appears to be a new transaction, then default
|
||||
* it to being a credit. If this transaction is already
|
||||
* in another account, assume this is the other half.
|
||||
* This algorithm is not robust against internal programming
|
||||
* errors ... various bizarre situations can sneak by without
|
||||
* warning ... however, this will do for now.
|
||||
*/
|
||||
|
||||
if ( !((_acc == trans->debit) || (_acc == trans->credit)) ) {
|
||||
if ( (NULL == trans->debit) && (NULL == trans->credit) ) {
|
||||
trans->credit = _acc;
|
||||
} else {
|
||||
if (NULL == trans->debit) {
|
||||
trans->debit = _acc;
|
||||
} else
|
||||
if (NULL == trans->credit) {
|
||||
trans->credit = _acc;
|
||||
} else
|
||||
{
|
||||
printf ("Internal Error: insertTransaction: inserting transaction \n");
|
||||
printf ("that already exists! \n");
|
||||
printf ("This error should not occur, please report it \n");
|
||||
}
|
||||
}
|
||||
printf ("Internal Error: insertTransaction(): \n");
|
||||
printf ("can't insert a transaction more than twice! \n");
|
||||
printf ("This error should not occur, please report it \n");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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++ )
|
||||
/* mark the data file as needing to be saved: */
|
||||
if( data != NULL )
|
||||
data->saved = False;
|
||||
|
||||
acc->numTrans++;
|
||||
oldTrans = acc->transaction;
|
||||
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) )
|
||||
{
|
||||
/* 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;
|
||||
break;
|
||||
j--;
|
||||
inserted = True;
|
||||
}
|
||||
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];
|
||||
}
|
||||
acc->transaction[i] = oldTrans[j];
|
||||
}
|
||||
|
||||
_free(oldTrans);
|
||||
}
|
||||
|
||||
_free(oldTrans);
|
||||
|
||||
if( position != -1 )
|
||||
qfInsertTransaction( acc->qfRoot, trans );
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Account *
|
||||
xaccGetOtherAccount( Account *acc, Transaction *trans )
|
||||
{
|
||||
struct _account * _acc = (struct _account *) acc;
|
||||
|
||||
if (NULL == acc) return NULL;
|
||||
|
||||
if (acc == ((Account *) trans->debit)) {
|
||||
return ((Account *) trans->credit);
|
||||
} else
|
||||
if (acc == ((Account *) trans->credit)) {
|
||||
return ((Account *) trans->debit);
|
||||
} else {
|
||||
printf ("Internal Error: xaccGetOtherAccount(): inconsistent entry \n");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@ -517,12 +551,10 @@ xaccCheckDateOrder (Account * acc, Transaction *trans )
|
||||
if (NULL == acc) return 0;
|
||||
|
||||
position = getNumOfTransaction (acc, trans);
|
||||
|
||||
/* if transaction not present in the account, its because
|
||||
* it hasn't been inserted yet. Insert it now. */
|
||||
if (-1 == position) {
|
||||
insertTransaction( acc, trans );
|
||||
return 1;
|
||||
printf ("Internal Error: xaccCheckDateOrder(): \n");
|
||||
printf ("transaction not present in the account !\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
prevTrans = getTransaction( acc, position-1 );
|
||||
|
156
src/Action.c
156
src/Action.c
@ -1,5 +1,5 @@
|
||||
/********************************************************************\
|
||||
* action.c -- account actions for xacc (X-Accountant) *
|
||||
* Action.c -- account actions for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Linas Vepstas *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
@ -19,161 +19,37 @@
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <ComboBox.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
|
||||
#include "Action.h"
|
||||
#include "PopBox.h"
|
||||
#include "util.h"
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
typedef struct _ActionBox {
|
||||
Widget combobox;
|
||||
Widget reg; /* the parent register widget */
|
||||
int currow;
|
||||
int curcol;
|
||||
} ActionBox;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
|
||||
void selectCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* actionBox *
|
||||
* creates the action widget *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* Return: actionData - the action GUI structure *
|
||||
* Return: PopBox - the action GUI structure *
|
||||
\********************************************************************/
|
||||
|
||||
#define ADD_MENU_ITEM(menustr) { \
|
||||
str = XmStringCreateLtoR (menustr, XmSTRING_DEFAULT_CHARSET); \
|
||||
XmComboBoxAddItem(combobox, str, 0); XmStringFree(str); \
|
||||
}
|
||||
|
||||
|
||||
ActionBox *
|
||||
PopBox *
|
||||
actionBox (Widget parent)
|
||||
{
|
||||
Widget combobox;
|
||||
XmString str;
|
||||
ActionBox *actionData;
|
||||
PopBox *popGUI;
|
||||
|
||||
/* malloc the action GUI structure */
|
||||
actionData = (ActionBox *) _malloc (sizeof (ActionBox));
|
||||
actionData->currow = -1;
|
||||
actionData->curcol = -1;
|
||||
actionData->reg = parent;
|
||||
|
||||
/* create the action GUI */
|
||||
combobox = XtVaCreateManagedWidget("actionbox", xmComboBoxWidgetClass, parent,
|
||||
XmNshadowThickness, 0, /* don't draw a shadow, use bae shadows */
|
||||
XmNeditable, False, /* user can only pick from list */
|
||||
XmNsorted, False,
|
||||
XmNshowLabel, False,
|
||||
XmNmarginHeight, 0,
|
||||
XmNmarginWidth, 0,
|
||||
XmNselectionPolicy, XmSINGLE_SELECT,
|
||||
XmNvalue, "",
|
||||
|
||||
/* hack alert -- the width of the combobox should be relative to the font, should
|
||||
be relative to the size of the cell in which it will fit. */
|
||||
XmNwidth, 43,
|
||||
NULL);
|
||||
|
||||
actionData -> combobox = combobox;
|
||||
popGUI = popBox (parent);
|
||||
|
||||
/* build the action menu */
|
||||
ADD_MENU_ITEM("Buy");
|
||||
ADD_MENU_ITEM("Sell");
|
||||
ADD_MENU_ITEM("Price");
|
||||
ADD_MENU_ITEM("Div");
|
||||
ADD_MENU_ITEM("LTCG");
|
||||
ADD_MENU_ITEM("STCG");
|
||||
ADD_MENU_ITEM("Dist");
|
||||
ADD_MENU_ITEM("Split");
|
||||
AddPopBoxMenuItem (popGUI, "Buy");
|
||||
AddPopBoxMenuItem (popGUI, "Sell");
|
||||
AddPopBoxMenuItem (popGUI, "Price");
|
||||
AddPopBoxMenuItem (popGUI, "Div");
|
||||
AddPopBoxMenuItem (popGUI, "LTCG");
|
||||
AddPopBoxMenuItem (popGUI, "STCG");
|
||||
AddPopBoxMenuItem (popGUI, "Dist");
|
||||
AddPopBoxMenuItem (popGUI, "Split");
|
||||
|
||||
/* add callbacks to detect a selection */
|
||||
XtAddCallback (combobox, XmNselectionCallback, selectCB, (XtPointer)actionData);
|
||||
XtAddCallback (combobox, XmNunselectionCallback, selectCB, (XtPointer)actionData);
|
||||
|
||||
|
||||
return actionData;
|
||||
return popGUI;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void SetActionBox (ActionBox *ab, int row, int col)
|
||||
{
|
||||
String choice;
|
||||
XmString choosen;
|
||||
|
||||
/* if the drop-down menu is showing, hide it now */
|
||||
XmComboBoxHideList (ab->combobox);
|
||||
|
||||
/* if there is an old widget, remove it */
|
||||
if ((0 <= ab->currow) && (0 <= ab->curcol)) {
|
||||
XbaeMatrixSetCellWidget (ab->reg, ab->currow, ab->curcol, NULL);
|
||||
}
|
||||
ab->currow = row;
|
||||
ab->curcol = col;
|
||||
|
||||
/* if the new position is valid, go to it,
|
||||
* otherwise, unmanage the widget */
|
||||
if ((0 <= ab->currow) && (0 <= ab->curcol)) {
|
||||
|
||||
/* Get the current cell contents, and set the
|
||||
* combobox menu selction to match the contents */
|
||||
choice = XbaeMatrixGetCell (ab->reg, ab->currow, ab->curcol);
|
||||
|
||||
/* do a menu selection only if the cell ain't empty. */
|
||||
if (0x0 != choice[0]) {
|
||||
/* convert String to XmString ... arghhh */
|
||||
choosen = XmCvtCTToXmString (choice);
|
||||
XmComboBoxSelectItem (ab->combobox, choosen, False);
|
||||
XmStringFree (choosen);
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (ab->combobox);
|
||||
}
|
||||
|
||||
/* set the cell widget */
|
||||
XbaeMatrixSetCellWidget (ab->reg, row, col, ab->combobox);
|
||||
|
||||
if (!XtIsManaged (ab->combobox)) {
|
||||
XtManageChild (ab->combobox);
|
||||
}
|
||||
|
||||
/* drop down the menu so that its ready to go. */
|
||||
XmComboBoxShowList (ab->combobox);
|
||||
} else {
|
||||
XtUnmanageChild (ab->combobox);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* selectCB -- get the user's selection, put the string into the *
|
||||
* cell. *
|
||||
* *
|
||||
* Args: w - the widget that called us *
|
||||
* cd - actionData - the data struct for this combobox *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
|
||||
void selectCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
|
||||
{
|
||||
ActionBox *ab = (ActionBox *) cd;
|
||||
XmComboBoxSelectionCallbackStruct *selection =
|
||||
(XmComboBoxSelectionCallbackStruct *) cb;
|
||||
char * choice;
|
||||
|
||||
choice = XmCvtXmStringToCT (selection->value);
|
||||
if (0x0 == choice) choice = "";
|
||||
|
||||
XbaeMatrixSetCell (ab->reg, ab->currow, ab->curcol, choice);
|
||||
|
||||
/* a diffeent way of getting the user's selection ... */
|
||||
/* text = XmComboBoxGetString (ab->combobox); */
|
||||
}
|
||||
/************************* END OF FILE ******************************/
|
||||
|
24
src/Data.c
24
src/Data.c
@ -108,6 +108,30 @@ xaccGetPeerAccountFromID ( Account *acc, int acc_id )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* Fetch an account, given it's name *
|
||||
\********************************************************************/
|
||||
|
||||
Account *
|
||||
xaccGetPeerAccountFromName ( Account *acc, char * name )
|
||||
{
|
||||
Data * data;
|
||||
Account *peer_acc;
|
||||
int i;
|
||||
|
||||
if (NULL == acc) return NULL;
|
||||
if (NULL == name) return NULL;
|
||||
|
||||
data = (Data *) acc->data;
|
||||
|
||||
for (i=0; i<data->numAcc; i++) {
|
||||
peer_acc = data->account[i];
|
||||
if (!strcmp(peer_acc->accountName, name)) return peer_acc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
Account *
|
||||
|
@ -415,7 +415,7 @@ mainWindow( Widget parent )
|
||||
|
||||
/********************************************************************\
|
||||
* closeMainWindow *
|
||||
* frees memory allocated for an regWindow, and other cleanup *
|
||||
* frees memory allocated for an mainWindow, and other cleanup *
|
||||
* stuff *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
|
@ -27,9 +27,9 @@
|
||||
# DO NOT EDIT THE STUFF BELOW THIS LINE! #
|
||||
|
||||
OBJS = Account.o AccWindow.o Action.o AdjBWindow.o BuildMenu.o Data.o date.o \
|
||||
FileBox.o FileIO.o HelpWindow.o main.o MainWindow.o \
|
||||
FileBox.o FileIO.o HelpWindow.o main.o MainWindow.o PopBox.o \
|
||||
QIFIO.o QuickFill.o RecnWindow.o RegWindow.o Reports.o \
|
||||
Transaction.o util.o XferWindow.o
|
||||
Transaction.o util.o XferBox.o XferWindow.o
|
||||
|
||||
SRCS = ${OBJS:.o=.c}
|
||||
|
||||
|
185
src/PopBox.c
Normal file
185
src/PopBox.c
Normal file
@ -0,0 +1,185 @@
|
||||
/********************************************************************\
|
||||
* Pop.c -- generic ComboBox for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Linas Vepstas *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
#include <ComboBox.h>
|
||||
#include <Xbae/Matrix.h>
|
||||
#include "util.h"
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
typedef struct _PopBox {
|
||||
Widget combobox;
|
||||
Widget reg; /* the parent register widget */
|
||||
int currow;
|
||||
int curcol;
|
||||
} PopBox;
|
||||
|
||||
/** PROTOTYPES ******************************************************/
|
||||
|
||||
void selectCB (Widget w, XtPointer cd, XtPointer cb );
|
||||
|
||||
/********************************************************************\
|
||||
* popBox *
|
||||
* creates the pop widget *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* Return: popData - the pop GUI structure *
|
||||
\********************************************************************/
|
||||
|
||||
PopBox *
|
||||
popBox (Widget parent)
|
||||
{
|
||||
Widget combobox;
|
||||
XmString str;
|
||||
PopBox *popData;
|
||||
|
||||
/* malloc the pop GUI structure */
|
||||
popData = (PopBox *) _malloc (sizeof (PopBox));
|
||||
popData->currow = -1;
|
||||
popData->curcol = -1;
|
||||
popData->reg = parent;
|
||||
|
||||
/* create the pop GUI */
|
||||
combobox = XtVaCreateManagedWidget("popbox", xmComboBoxWidgetClass, parent,
|
||||
XmNshadowThickness, 0, /* don't draw a shadow, use bae shadows */
|
||||
XmNeditable, False, /* user can only pick from list */
|
||||
XmNsorted, False,
|
||||
XmNshowLabel, False,
|
||||
XmNmarginHeight, 0,
|
||||
XmNmarginWidth, 0,
|
||||
XmNselectionPolicy, XmSINGLE_SELECT,
|
||||
XmNvalue, "",
|
||||
|
||||
/* hack alert -- the width of the combobox should be relative to the font, should
|
||||
be relative to the size of the cell in which it will fit. */
|
||||
XmNwidth, 53,
|
||||
NULL);
|
||||
|
||||
popData -> combobox = combobox;
|
||||
|
||||
/* add callbacks to detect a selection */
|
||||
XtAddCallback (combobox, XmNselectionCallback, selectCB, (XtPointer)popData);
|
||||
XtAddCallback (combobox, XmNunselectionCallback, selectCB, (XtPointer)popData);
|
||||
|
||||
return popData;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* AddPopBoxMenuItem *
|
||||
* add a menu item to the pop box *
|
||||
* *
|
||||
* Args: PopBox - the pop GUI structure *
|
||||
* menustr -- the menu entry to be added *
|
||||
* Return: void *
|
||||
\********************************************************************/
|
||||
|
||||
void AddPopBoxMenuItem (PopBox *ab, char * menustr)
|
||||
{
|
||||
XmString str;
|
||||
str = XmStringCreateLtoR (menustr, XmSTRING_DEFAULT_CHARSET);
|
||||
XmComboBoxAddItem (ab->combobox, str, 0);
|
||||
XmStringFree (str);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* SetPopBox *
|
||||
* moves the ComboBox to the indicated column, row *
|
||||
* *
|
||||
* Args: PopBox - the pop GUI structure *
|
||||
* row -- the row of the Xbae Matrix *
|
||||
* col -- the col of the Xbae Matrix *
|
||||
* Return: void *
|
||||
\********************************************************************/
|
||||
|
||||
|
||||
void SetPopBox (PopBox *ab, int row, int col)
|
||||
{
|
||||
String choice;
|
||||
XmString choosen;
|
||||
|
||||
/* if the drop-down menu is showing, hide it now */
|
||||
XmComboBoxHideList (ab->combobox);
|
||||
|
||||
/* if there is an old widget, remove it */
|
||||
if ((0 <= ab->currow) && (0 <= ab->curcol)) {
|
||||
XbaeMatrixSetCellWidget (ab->reg, ab->currow, ab->curcol, NULL);
|
||||
}
|
||||
ab->currow = row;
|
||||
ab->curcol = col;
|
||||
|
||||
/* if the new position is valid, go to it,
|
||||
* otherwise, unmanage the widget */
|
||||
if ((0 <= ab->currow) && (0 <= ab->curcol)) {
|
||||
|
||||
/* Get the current cell contents, and set the
|
||||
* combobox menu selction to match the contents */
|
||||
choice = XbaeMatrixGetCell (ab->reg, ab->currow, ab->curcol);
|
||||
|
||||
/* do a menu selection only if the cell ain't empty. */
|
||||
if (0x0 != choice[0]) {
|
||||
/* convert String to XmString ... arghhh */
|
||||
choosen = XmCvtCTToXmString (choice);
|
||||
XmComboBoxSelectItem (ab->combobox, choosen, False);
|
||||
XmStringFree (choosen);
|
||||
} else {
|
||||
XmComboBoxClearItemSelection (ab->combobox);
|
||||
}
|
||||
|
||||
/* set the cell widget */
|
||||
XbaeMatrixSetCellWidget (ab->reg, row, col, ab->combobox);
|
||||
|
||||
if (!XtIsManaged (ab->combobox)) {
|
||||
XtManageChild (ab->combobox);
|
||||
}
|
||||
|
||||
/* drop down the menu so that its ready to go. */
|
||||
XmComboBoxShowList (ab->combobox);
|
||||
} else {
|
||||
XtUnmanageChild (ab->combobox);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* selectCB -- get the user's selection, put the string into the *
|
||||
* cell. *
|
||||
* *
|
||||
* Args: w - the widget that called us *
|
||||
* cd - popData - the data struct for this combobox *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
|
||||
void selectCB (Widget w, XtPointer cd, XtPointer cb )
|
||||
|
||||
{
|
||||
PopBox *ab = (PopBox *) cd;
|
||||
XmComboBoxSelectionCallbackStruct *selection =
|
||||
(XmComboBoxSelectionCallbackStruct *) cb;
|
||||
char * choice;
|
||||
|
||||
choice = XmCvtXmStringToCT (selection->value);
|
||||
if (0x0 == choice) choice = "";
|
||||
|
||||
XbaeMatrixSetCell (ab->reg, ab->currow, ab->curcol, choice);
|
||||
|
||||
/* a diffeent way of getting the user's selection ... */
|
||||
/* text = XmComboBoxGetString (ab->combobox); */
|
||||
}
|
||||
/************************* END OF FILE ******************************/
|
@ -113,17 +113,21 @@ qfInsertTransactionRec( QuickFill *qf, Transaction *trans, int depth )
|
||||
{
|
||||
if( qf != NULL )
|
||||
{
|
||||
if( trans->description[depth] != '\0' )
|
||||
if( trans->description )
|
||||
{
|
||||
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 );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************** END OF FILE *********************************\
|
||||
\********************************************************************/
|
||||
|
415
src/RegWindow.c
415
src/RegWindow.c
@ -35,13 +35,14 @@
|
||||
#include <Xbae/Matrix.h>
|
||||
|
||||
#include "Account.h"
|
||||
#include "ActionBox.h"
|
||||
#include "Action.h"
|
||||
#include "AdjBWindow.h"
|
||||
#include "BuildMenu.h"
|
||||
#include "Data.h"
|
||||
#include "date.h"
|
||||
#include "main.h"
|
||||
#include "MainWindow.h"
|
||||
#include "PopBox.h"
|
||||
#include "QuickFill.h"
|
||||
#include "RecnWindow.h"
|
||||
#include "Transaction.h"
|
||||
@ -62,7 +63,8 @@ typedef struct _RegWindow {
|
||||
QuickFill *qf; /* keeps track of current quickfill node. *
|
||||
* Reset to Account->qfRoot when entering *
|
||||
* a new transaction */
|
||||
ActionBox *ab;
|
||||
PopBox *actbox; /* ComboBox for actions */
|
||||
PopBox *xferbox; /* ComboBox for transfers */
|
||||
} RegWindow;
|
||||
|
||||
|
||||
@ -106,8 +108,9 @@ extern Pixel negPixel;
|
||||
#define MOD_PRIC 0x40
|
||||
#define MOD_MEMO 0x80
|
||||
#define MOD_ACTN 0x100
|
||||
#define MOD_NEW 0x200
|
||||
#define MOD_ALL 0x3ff
|
||||
#define MOD_XFER 0x200
|
||||
#define MOD_NEW 0x400
|
||||
#define MOD_ALL 0x7ff
|
||||
|
||||
/* These defines are indexes into the column location array */
|
||||
#define DATE_COL_ID 0
|
||||
@ -141,10 +144,14 @@ extern Pixel negPixel;
|
||||
#define SHRS_CELL_C (acc->columnLocation[SHRS_COL_ID])
|
||||
#define ACTN_CELL_C (acc->columnLocation[ACTN_COL_ID])
|
||||
|
||||
#define YEAR_CELL_R 1
|
||||
#define YEAR_CELL_C DATE_CELL_C /* same column as the date */
|
||||
#define XFER_CELL_R 1
|
||||
#define XFER_CELL_C NUM_CELL_C /* same column as the transaction number */
|
||||
#define MEMO_CELL_R 1
|
||||
#define MEMO_CELL_C DESC_CELL_C /* same cilumn as the description */
|
||||
#define MEMO_CELL_C DESC_CELL_C /* same column as the description */
|
||||
|
||||
/** COOL MACROS *****************************************************/
|
||||
/** CELL MACROS *****************************************************/
|
||||
#define IN_DATE_CELL(R,C) (((R-1)%2==0) && (C==DATE_CELL_C)) /* Date cell */
|
||||
#define IN_NUM_CELL(R,C) (((R-1)%2==0) && (C==NUM_CELL_C)) /* Number cell */
|
||||
#define IN_DESC_CELL(R,C) (((R-1)%2==0) && (C==DESC_CELL_C)) /* Description cell */
|
||||
@ -156,6 +163,7 @@ extern Pixel negPixel;
|
||||
#define IN_ACTN_CELL(R,C) (((R-1)%2==0) && (C==ACTN_CELL_C)) /* Action cell */
|
||||
|
||||
#define IN_YEAR_CELL(R,C) (((R-1)%2==1) && (C==DATE_CELL_C)) /* Year cell */
|
||||
#define IN_XFER_CELL(R,C) (((R-1)%2==1) && (C==XFER_CELL_C)) /* Transfer cell */
|
||||
#define IN_MEMO_CELL(R,C) (((R-1)%2==1) && (C==MEMO_CELL_C)) /* Memo cell */
|
||||
#define IN_BAD_CELL(R,C) (((R-1)%2==1) && (C!=MEMO_CELL_C)) /* Not the memo cell*/
|
||||
|
||||
@ -181,7 +189,7 @@ regRefresh( RegWindow *regData )
|
||||
char buf[BUFSIZE];
|
||||
String **data = NULL;
|
||||
String **newData;
|
||||
Account *acc;
|
||||
Account *acc, *xfer_acc;
|
||||
double themount; /* amount */
|
||||
|
||||
XtVaGetValues( regData->reg, XmNrows, &nrows, NULL );
|
||||
@ -214,7 +222,7 @@ regRefresh( RegWindow *regData )
|
||||
|
||||
/* and fill in the data for the matrix: */
|
||||
i=-1;
|
||||
while( (trans=getTransaction(regData->acc,++i)) != NULL )
|
||||
while( (trans = getTransaction (acc,++i)) != NULL )
|
||||
{
|
||||
int row = i*2+1;
|
||||
|
||||
@ -222,25 +230,29 @@ regRefresh( RegWindow *regData )
|
||||
trans->date.month,
|
||||
trans->date.day );
|
||||
newData[row][DATE_CELL_C] = XtNewString(buf);
|
||||
|
||||
sprintf( buf, "%4d", trans->date.year );
|
||||
newData[row+1][DATE_CELL_C] = XtNewString(buf);
|
||||
newData[row+1][DATE_CELL_C] = XtNewString(buf); /* YEAR_CELL_C */
|
||||
|
||||
sprintf( buf, "%s", trans->num );
|
||||
newData[row][NUM_CELL_C] = XtNewString(buf);
|
||||
|
||||
newData[row+1][NUM_CELL_C] = XtNewString("");
|
||||
|
||||
/* XFER_CELL_C is same as NUM_CELL_C */
|
||||
xfer_acc = xaccGetOtherAccount (acc, trans);
|
||||
if (xfer_acc) {
|
||||
sprintf( buf, "%s", xfer_acc->accountName );
|
||||
newData[row+1][NUM_CELL_C] = XtNewString(buf);
|
||||
} else {
|
||||
newData[row+1][NUM_CELL_C] = XtNewString("");
|
||||
}
|
||||
|
||||
|
||||
sprintf( buf, "%s", trans->description );
|
||||
newData[row][DESC_CELL_C] = XtNewString(buf);
|
||||
|
||||
sprintf( buf, "%s", trans->memo );
|
||||
newData[row+1][DESC_CELL_C] = XtNewString(buf);
|
||||
|
||||
sprintf( buf, "%c", trans->reconciled );
|
||||
newData[row][RECN_CELL_C] = XtNewString(buf);
|
||||
|
||||
newData[row+1][RECN_CELL_C] = XtNewString("");
|
||||
|
||||
/* ----------------------------------- */
|
||||
@ -463,50 +475,112 @@ regRecalculateBalance( RegWindow *regData )
|
||||
* Global: data - the data for open datafile *
|
||||
\********************************************************************/
|
||||
|
||||
#define RECALC_BALANCE(sacc) { \
|
||||
Account * xfer_acc; \
|
||||
RegWindow * xfer_reg; \
|
||||
xfer_acc = (Account *) (sacc); \
|
||||
if (xfer_acc) { \
|
||||
xfer_reg = (RegWindow *) (xfer_acc->regData); \
|
||||
if (xfer_reg) { \
|
||||
regRecalculateBalance (xfer_reg); \
|
||||
} \
|
||||
} \
|
||||
/* RECALC_BALANCE recomputes the balance shown in
|
||||
* the register window, if its is visible
|
||||
*/
|
||||
|
||||
#define RECALC_BALANCE(sacc) { \
|
||||
Account * xfer_acc; \
|
||||
RegWindow * xfer_reg; \
|
||||
xfer_acc = (Account *) (sacc); \
|
||||
if (xfer_acc) { \
|
||||
xfer_reg = (RegWindow *) (xfer_acc->regData); \
|
||||
if (xfer_reg) { \
|
||||
regRecalculateBalance (xfer_reg); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* REFRESH_REGISTER redisplays the register window,
|
||||
* if it is visible
|
||||
*/
|
||||
#define REFRESH_REGISTER(sacc) { \
|
||||
Account * xfer_acc; \
|
||||
RegWindow * xfer_reg; \
|
||||
xfer_acc = (Account *) (sacc); \
|
||||
if (xfer_acc) { \
|
||||
xfer_reg = (RegWindow *) (xfer_acc->regData); \
|
||||
if (xfer_reg) { \
|
||||
regRefresh (xfer_reg); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* DATE_REORDER needs to null out lastTrans, because
|
||||
* during date reordering we removed and re-inserted
|
||||
* the transaction... reset lastTrans to zero to prevent it from
|
||||
* indicating a row that doesn't exist. (That shouldn't happen
|
||||
* anyways!)
|
||||
*/
|
||||
#define DATE_REORDER(sacc) { \
|
||||
Account * xfer_acc; \
|
||||
RegWindow * xfer_reg; \
|
||||
xfer_acc = (Account *) (sacc); \
|
||||
if (xfer_acc) { \
|
||||
xfer_reg = (RegWindow *) (xfer_acc->regData); \
|
||||
if (xfer_reg) { \
|
||||
xfer_reg->lastTrans = 0; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* REMOVE_TRANS will not only remove a transaction from an account,
|
||||
* but it will also delete the appropriate rows from the register
|
||||
* window, if the register window is visible
|
||||
*/
|
||||
#define REMOVE_TRANS(sacc,trans) { \
|
||||
Account *otherAcc = (Account *) (sacc); \
|
||||
if (otherAcc) { \
|
||||
RegWindow *otherRegData = otherAcc -> regData; \
|
||||
int n = getNumOfTransaction (otherAcc, trans); \
|
||||
\
|
||||
/* remove the transaction */ \
|
||||
xaccRemoveTransaction( otherAcc, trans ); \
|
||||
\
|
||||
/* remove the rows from the matrix */ \
|
||||
if (otherRegData) { \
|
||||
int otherrow = 2*n + 1; \
|
||||
XbaeMatrixDeleteRows( otherRegData->reg, otherrow, 2 ); \
|
||||
XbaeMatrixRefresh( otherRegData->reg); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void
|
||||
regSaveTransaction( RegWindow *regData, int position )
|
||||
{
|
||||
{
|
||||
/* save transaction structure... in order to speed this up,
|
||||
* regData->changed is a bitfield that keeps track of things
|
||||
* that might have changed, so we only have to save the stuff
|
||||
* that has changed */
|
||||
char buf[BUFSIZE];
|
||||
int newPosition;
|
||||
int row = (position * 2) + 1;
|
||||
Account *acc;
|
||||
Account *acc = regData->acc;
|
||||
Transaction *trans;
|
||||
|
||||
acc = regData->acc;
|
||||
/* If nothing has changed, we have nothing to do */
|
||||
if (MOD_NONE == regData->changed) return;
|
||||
|
||||
/* Be sure to prompt the user to save to disk after changes are made! */
|
||||
acc->data->saved = False;
|
||||
|
||||
trans = getTransaction( acc, position );
|
||||
|
||||
/* If anything changes, we have to set this flag, so we
|
||||
* remember to prompt the user to save! */
|
||||
if( MOD_NONE != regData->changed )
|
||||
data->saved = False;
|
||||
|
||||
if( trans == NULL )
|
||||
{
|
||||
/* This must be a new transaction */
|
||||
DEBUG("New Transaction");
|
||||
|
||||
/* If nothing has changed, we don't want to save this */
|
||||
if( !(regData->changed & MOD_ALL) )
|
||||
return;
|
||||
|
||||
trans = mallocTransaction();
|
||||
trans->credit = (struct _account *) acc;
|
||||
|
||||
/* insert the transaction now. If we later discover that
|
||||
* the user hs not made any entries, we will remove it again.
|
||||
* However, for some of the itntermediate processing, we must
|
||||
* have a valid transaction present in the account.
|
||||
*/
|
||||
insertTransaction (acc, trans);
|
||||
regData->changed = MOD_ALL;
|
||||
}
|
||||
if( regData->changed & MOD_NUM )
|
||||
@ -517,6 +591,34 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
trans->num = XtNewString( XbaeMatrixGetCell(regData->reg,row,NUM_CELL_C) );
|
||||
}
|
||||
|
||||
if( regData->changed & MOD_XFER )
|
||||
{
|
||||
/* ... the transfer ... */
|
||||
char * name;
|
||||
Account *xfer_acct = xaccGetOtherAccount (acc, trans);
|
||||
DEBUG("MOD_XFER");
|
||||
|
||||
if (xfer_acct) {
|
||||
/* remove the transaction from wherever it used to be */
|
||||
REMOVE_TRANS (xfer_acct, trans);
|
||||
|
||||
/* recalculate the balance and redisplay the window for the old acct */
|
||||
RECALC_BALANCE (xfer_acct);
|
||||
REFRESH_REGISTER (xfer_acct);
|
||||
}
|
||||
|
||||
/* get the new account name */
|
||||
name = XbaeMatrixGetCell(regData->reg,row+XFER_CELL_R, XFER_CELL_C);
|
||||
|
||||
/* get the new account from the name */
|
||||
xfer_acct = xaccGetPeerAccountFromName (acc, name);
|
||||
|
||||
if (xfer_acct) {
|
||||
/* insert the transaction into the new account */
|
||||
insertTransaction (xfer_acct, trans);
|
||||
}
|
||||
}
|
||||
|
||||
if( regData->changed & MOD_DESC )
|
||||
{
|
||||
DEBUG("MOD_DESC");
|
||||
@ -533,34 +635,13 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
DEBUG("MOD_MEMO");
|
||||
/* ... the memo ... */
|
||||
XtFree( trans->memo );
|
||||
|
||||
tmp = XbaeMatrixGetCell(regData->reg,row+1,MEMO_CELL_C);
|
||||
|
||||
/* if its a transfer, indicate where its from ... */
|
||||
/* hack alert -- this algorithm is fundamentally broken if
|
||||
* memo field is repeatedly edited ... */
|
||||
if ((NULL != trans->debit) && (NULL != trans->credit)) {
|
||||
Account *fromAccount = NULL;
|
||||
if (acc == ((Account *) trans->debit) ) {
|
||||
fromAccount = (Account *) trans->credit;
|
||||
} else {
|
||||
fromAccount = (Account *) trans->debit;
|
||||
}
|
||||
/* Get the memo, and add the "from" account name to it */
|
||||
memo = (String)malloc (strlen(tmp)+
|
||||
strlen(fromAccount->accountName)+
|
||||
strlen("[From: ] ") );
|
||||
|
||||
sprintf( memo, "[From: %s] %s\0", fromAccount->accountName, tmp);
|
||||
|
||||
XbaeMatrixSetCell( regData->reg, row+1, MEMO_CELL_C, memo );
|
||||
trans->memo = memo;
|
||||
} else {
|
||||
trans->memo = XtNewString( tmp );
|
||||
}
|
||||
tmp = XbaeMatrixGetCell(regData->reg,row+MEMO_CELL_R,MEMO_CELL_C);
|
||||
trans->memo = XtNewString( tmp );
|
||||
}
|
||||
|
||||
if( regData->changed & MOD_ACTN )
|
||||
/* ignore MOD_ACTN for non-stock accounts */
|
||||
if( (regData->changed & MOD_ACTN) &&
|
||||
((MUTUAL == acc->type) || (PORTFOLIO==acc->type)) )
|
||||
{
|
||||
String actn = NULL;
|
||||
DEBUG("MOD_ACTN");
|
||||
@ -575,10 +656,6 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
DEBUG("MOD_RECN");
|
||||
/* ...the reconciled flag (char)... */
|
||||
trans->reconciled = (XbaeMatrixGetCell(regData->reg,row,RECN_CELL_C))[0];
|
||||
|
||||
/* Remember, we need to recalculate the reconciled balance now! */
|
||||
RECALC_BALANCE ((trans->credit));
|
||||
RECALC_BALANCE ((trans->debit));
|
||||
}
|
||||
|
||||
if( regData->changed & MOD_AMNT )
|
||||
@ -603,7 +680,7 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
/* Reset so there is only one field filled */
|
||||
if( 0.0 > themount )
|
||||
{
|
||||
/* hack alert -- keep 3 digits for share amounts */
|
||||
/* hack alert -- should keep 3 digits for share amounts */
|
||||
sprintf( buf, "%.2f ", -themount );
|
||||
XbaeMatrixSetCell( regData->reg, row, PAY_CELL_C, buf );
|
||||
XbaeMatrixSetCell( regData->reg, row, DEP_CELL_C, "" );
|
||||
@ -614,12 +691,9 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
XbaeMatrixSetCell( regData->reg, row, PAY_CELL_C, "" );
|
||||
XbaeMatrixSetCell( regData->reg, row, DEP_CELL_C, buf );
|
||||
}
|
||||
|
||||
RECALC_BALANCE ((trans->credit));
|
||||
RECALC_BALANCE ((trans->debit));
|
||||
}
|
||||
|
||||
/* ignore MOD_PRIC if for non-stock accounts */
|
||||
/* ignore MOD_PRIC for non-stock accounts */
|
||||
if( (regData->changed & MOD_PRIC) &&
|
||||
((MUTUAL == acc->type) || (PORTFOLIO==acc->type)) )
|
||||
{
|
||||
@ -635,91 +709,70 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
|
||||
sprintf( buf, "%.2f ", trans->share_price );
|
||||
XbaeMatrixSetCell( regData->reg, row, PRIC_CELL_C, buf );
|
||||
|
||||
/* Remember, we need to recalculate the reconciled balance now! */
|
||||
RECALC_BALANCE ((trans->credit));
|
||||
RECALC_BALANCE ((trans->debit));
|
||||
}
|
||||
|
||||
/* Before we check the date, and possibly insert the new
|
||||
* transaction, we need to make sure that, if this is a
|
||||
* new transaction, that the user actually entered some
|
||||
* data! Otherwise, it would be lame to add this. */
|
||||
if( regData->changed & MOD_NEW )
|
||||
if( regData->changed & MOD_DATE )
|
||||
{
|
||||
Boolean outOfOrder = False;
|
||||
|
||||
DEBUG("MOD_DATE");
|
||||
/* read in the date stuff... */
|
||||
sscanf( XbaeMatrixGetCell(regData->reg,row+DATE_CELL_R,DATE_CELL_C),"%d/%d",
|
||||
&(trans->date.month),
|
||||
&(trans->date.day) );
|
||||
|
||||
trans->date.year = atoi(XbaeMatrixGetCell(regData->reg,row+YEAR_CELL_R,YEAR_CELL_C));
|
||||
|
||||
/* take care of re-ordering implications on the register.
|
||||
* If the date changed on a double-entry (transfer) transaction,
|
||||
* then make sure that both register windows are updated .. */
|
||||
outOfOrder = xaccCheckDateOrderDE (trans);
|
||||
if( outOfOrder )
|
||||
{
|
||||
int pos;
|
||||
|
||||
DATE_REORDER ((trans->credit));
|
||||
DATE_REORDER ((trans->debit));
|
||||
|
||||
/* Scroll to the new location of the reordered transaction;
|
||||
* but do this only for this register, not any other register
|
||||
* windows. */
|
||||
pos = getNumOfTransaction (acc, trans);
|
||||
XbaeMatrixMakeCellVisible( regData->reg, 2*pos+1, DESC_CELL_C );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a new transaction, and the user did not
|
||||
* actually enter any data, then we should not really
|
||||
* consider this to be a new transaction! */
|
||||
if (regData->changed & MOD_NEW) {
|
||||
if( (strcmp("",trans->num) == 0) &&
|
||||
(strcmp("",trans->description) == 0) &&
|
||||
(strcmp("",trans->memo) == 0) &&
|
||||
(strcmp("",trans->action) == 0) &&
|
||||
(0 == trans->catagory) &&
|
||||
(NULL == xaccGetOtherAccount (acc, trans)) &&
|
||||
(NULL == trans->debit) &&
|
||||
(1.0 == trans->share_price) &&
|
||||
(0.0 == trans->damount) )
|
||||
(0.0 == trans->damount) )
|
||||
{
|
||||
_free(trans);
|
||||
xaccRemoveTransaction (acc, trans);
|
||||
freeTransaction (trans);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( regData->changed & MOD_DATE )
|
||||
{
|
||||
Transaction *prevTrans;
|
||||
Transaction *nextTrans;
|
||||
Boolean outOfOrder = False;
|
||||
prevTrans = getTransaction( acc, position-1 );
|
||||
nextTrans = getTransaction( acc, position+1 );
|
||||
|
||||
DEBUG("MOD_DATE");
|
||||
/* read in the date stuff... */
|
||||
sscanf( XbaeMatrixGetCell(regData->reg,row,DATE_CELL_C),"%d/%d",
|
||||
&(trans->date.month),
|
||||
&(trans->date.day) );
|
||||
|
||||
trans->date.year = atoi(XbaeMatrixGetCell(regData->reg,row+1,DATE_CELL_C));
|
||||
|
||||
/* figure out if the transactions are out of order */
|
||||
outOfOrder = xaccCheckDateOrderDE (trans);
|
||||
|
||||
/* take care of re-ordering implications on the register, if necessary */
|
||||
if( outOfOrder )
|
||||
{
|
||||
|
||||
/* REFRESH_REGISTER needs to null out lastTrans, because
|
||||
* during date reordering we removed and re-inserted
|
||||
* the transaction... reset lastTrans to zero to prevent it from
|
||||
* indicating a row that doesn't exist. (That shouldn't happen
|
||||
* anyways!) */
|
||||
#define REFRESH_REGISTER(sacc) { \
|
||||
Account * xfer_acc; \
|
||||
RegWindow * xfer_reg; \
|
||||
xfer_acc = (Account *) (sacc); \
|
||||
if (xfer_acc) { \
|
||||
xfer_reg = (RegWindow *) (xfer_acc->regData); \
|
||||
if (xfer_reg) { \
|
||||
xfer_reg->lastTrans = 0; \
|
||||
regRefresh (xfer_reg); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* if the date changed on a double-entry (transfer) transaction,
|
||||
* then make sure that both register windows are updated .. */
|
||||
|
||||
REFRESH_REGISTER ((trans->credit));
|
||||
REFRESH_REGISTER ((trans->debit));
|
||||
}
|
||||
|
||||
/* Scroll to the last row, if it is a new transaction */
|
||||
if( !(regData->changed & MOD_NEW) )
|
||||
{
|
||||
int lastRow = (2 * newPosition) + 1 + DESC_CELL_C;
|
||||
XbaeMatrixMakeCellVisible( regData->reg, lastRow, DESC_CELL_C );
|
||||
}
|
||||
|
||||
/* recalculate the balances, but only after re-ordering cells */
|
||||
/* For many, but not all changes, we need to
|
||||
* recalculate the balances */
|
||||
if( regData->changed & (MOD_XFER | MOD_RECN | MOD_AMNT | MOD_PRIC | MOD_NEW)) {
|
||||
RECALC_BALANCE ((trans->credit));
|
||||
RECALC_BALANCE ((trans->debit));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
REFRESH_REGISTER ((trans->credit));
|
||||
REFRESH_REGISTER ((trans->debit));
|
||||
|
||||
/* reset the "changed" bitfield */
|
||||
regData->changed = 0;
|
||||
|
||||
@ -738,7 +791,7 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
REFRESH_RECONCILE_WIN ((trans->debit));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* regWindow *
|
||||
@ -812,7 +865,7 @@ regWindow( Widget parent, Account *acc )
|
||||
XmNmarginWidth, 1,
|
||||
XmNallowResize, True,
|
||||
XmNpaneMaximum, 200,
|
||||
XmNpaneMinimum, 200,
|
||||
XmNpaneMinimum, 800,
|
||||
NULL );
|
||||
|
||||
/* Setup the menubar at the top of the window */
|
||||
@ -867,7 +920,7 @@ regWindow( Widget parent, Account *acc )
|
||||
activityMenu[2].callback_data=(XtPointer)regData;
|
||||
activityMenu[3].callback_data=(XtPointer)regData;
|
||||
activityMenu[6].callback_data=(XtPointer)regData;
|
||||
activityMenu[8].callback_data=(XtPointer)(regData->dialog);
|
||||
activityMenu[8].callback_data=(XtPointer)(regData->dialog); /* destroy callback */
|
||||
|
||||
menubar = XmCreateMenuBar( pane, "menubar", NULL, 0 );
|
||||
|
||||
@ -932,13 +985,13 @@ regWindow( Widget parent, Account *acc )
|
||||
/* ----------------------------------- */
|
||||
/* set up column widths */
|
||||
|
||||
acc -> colWidths[DATE_CELL_C] = 5; /* the widths of columns */
|
||||
acc -> colWidths[NUM_CELL_C] = 4; /* the widths of columns */
|
||||
acc -> colWidths[DESC_CELL_C] = 35; /* the widths of columns */
|
||||
acc -> colWidths[DATE_CELL_C] = 5; /* also YEAR_CELL_C */
|
||||
acc -> colWidths[NUM_CELL_C] = 8; /* also XFER_CELL_C */
|
||||
acc -> colWidths[DESC_CELL_C] = 35; /* also MEMO_CELL_C */
|
||||
acc -> colWidths[RECN_CELL_C] = 1; /* the widths of columns */
|
||||
acc -> colWidths[PAY_CELL_C] = 8; /* the widths of columns */
|
||||
acc -> colWidths[DEP_CELL_C] = 8; /* the widths of columns */
|
||||
acc -> colWidths[BALN_CELL_C] = 8; /* $ balance */
|
||||
acc -> colWidths[PAY_CELL_C] = 12; /* the widths of columns */
|
||||
acc -> colWidths[DEP_CELL_C] = 12; /* the widths of columns */
|
||||
acc -> colWidths[BALN_CELL_C] = 12; /* dollar balance */
|
||||
|
||||
switch(acc->type)
|
||||
{
|
||||
@ -960,7 +1013,7 @@ regWindow( Widget parent, Account *acc )
|
||||
/* set up column alignments */
|
||||
|
||||
acc -> alignments[DATE_CELL_C] = XmALIGNMENT_END;
|
||||
acc -> alignments[NUM_CELL_C] = XmALIGNMENT_END;
|
||||
acc -> alignments[NUM_CELL_C] = XmALIGNMENT_BEGINNING; /* need XFER to be visible */
|
||||
acc -> alignments[DESC_CELL_C] = XmALIGNMENT_BEGINNING;
|
||||
acc -> alignments[RECN_CELL_C] = XmALIGNMENT_CENTER;
|
||||
acc -> alignments[PAY_CELL_C] = XmALIGNMENT_END;
|
||||
@ -1078,8 +1131,11 @@ regWindow( Widget parent, Account *acc )
|
||||
|
||||
|
||||
/* create action box for the first time */
|
||||
regData->ab = actionBox (reg);
|
||||
|
||||
regData->actbox = actionBox (reg);
|
||||
|
||||
/* create the xfer account box for the first time */
|
||||
regData->xferbox = xferBox (reg, data);
|
||||
|
||||
|
||||
/******************************************************************\
|
||||
* The button area... also contains balance fields *
|
||||
@ -1197,8 +1253,9 @@ regWindow( Widget parent, Account *acc )
|
||||
|
||||
XtPopup( regData->dialog, XtGrabNone );
|
||||
|
||||
/* unmanage the action box, until it is needed */
|
||||
SetActionBox (regData->ab, -1, -1);
|
||||
/* unmanage the ComboBoxes, until they are needed */
|
||||
SetPopBox (regData->actbox, -1, -1);
|
||||
SetPopBox (regData->xferbox, -1, -1);
|
||||
|
||||
unsetBusyCursor( parent );
|
||||
|
||||
@ -1219,12 +1276,16 @@ void
|
||||
closeRegWindow( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
RegWindow *regData = (RegWindow *)cd;
|
||||
Account *acc = regData->acc;
|
||||
Account *acc;
|
||||
|
||||
acc = regData->acc;
|
||||
|
||||
/* Save any unsaved changes */
|
||||
XbaeMatrixCommitEdit( regData->reg, False );
|
||||
regSaveTransaction( regData, regData->lastTrans );
|
||||
|
||||
/* hack alert -- free the ComboBox popup boxes data structures too */
|
||||
|
||||
_free(regData);
|
||||
acc->regData = NULL;
|
||||
|
||||
@ -1291,24 +1352,6 @@ recordCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
|
||||
#define REMOVE_TRANS(sacc,trans) { \
|
||||
Account *otherAcc = (Account *) (sacc); \
|
||||
if (otherAcc) { \
|
||||
RegWindow *otherRegData = otherAcc -> regData; \
|
||||
int n = getNumOfTransaction (otherAcc, trans); \
|
||||
\
|
||||
/* remove the transaction */ \
|
||||
trans = removeTransaction( otherAcc, n ); \
|
||||
\
|
||||
/* remove the rows from the matrix */ \
|
||||
if (otherRegData) { \
|
||||
int otherrow = 2*n + 1; \
|
||||
XbaeMatrixDeleteRows( otherRegData->reg, otherrow, 2 ); \
|
||||
XbaeMatrixRefresh( otherRegData->reg); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void
|
||||
deleteCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
@ -1362,7 +1405,7 @@ cancelCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
* add an undo/cancel modifications feature *
|
||||
* *
|
||||
* Args: mw - the widget that called us *
|
||||
* cd - regData - the data struct for this register *
|
||||
* cd - regData - the data struct for this register *
|
||||
* cb - *
|
||||
* Return: none *
|
||||
\********************************************************************/
|
||||
@ -1409,6 +1452,7 @@ regCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
if( !IN_DATE_CELL(row,col) && !IN_NUM_CELL(row,col) &&
|
||||
!IN_DESC_CELL(row,col) && !IN_PAY_CELL(row,col) &&
|
||||
!IN_RECN_CELL(row,col) && !IN_DEP_CELL(row,col) &&
|
||||
!IN_XFER_CELL(row,col) &&
|
||||
!((PORTFOLIO == acc->type) && IN_PRIC_CELL(row,col)) &&
|
||||
!((MUTUAL == acc->type) && IN_PRIC_CELL(row,col)) &&
|
||||
!((PORTFOLIO == acc->type) && IN_ACTN_CELL(row,col)) &&
|
||||
@ -1444,9 +1488,16 @@ regCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
else if( ((PORTFOLIO == acc->type) && IN_ACTN_CELL(row,col)) ||
|
||||
((MUTUAL == acc->type) && IN_ACTN_CELL(row,col)) )
|
||||
{
|
||||
SetActionBox (regData->ab, row, col);
|
||||
SetPopBox (regData->actbox, row, col);
|
||||
regData->changed |= MOD_ACTN;
|
||||
}
|
||||
|
||||
/* otherwise, move the XFER widget */
|
||||
else if( IN_XFER_CELL(row,col) )
|
||||
{
|
||||
SetPopBox (regData->xferbox, row, col);
|
||||
regData->changed |= MOD_XFER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1618,7 +1669,15 @@ regCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
((MUTUAL == acc->type) && IN_ACTN_CELL(row,col)) ) {
|
||||
regData->changed |= MOD_ACTN;
|
||||
}
|
||||
/* Note: for cell widgets, this callback will never
|
||||
* indicate a row,col with a cell widget in it.
|
||||
* Thus, the following if statment will never be true
|
||||
*/
|
||||
if( IN_XFER_CELL(row,col) )
|
||||
regData->changed |= MOD_XFER;
|
||||
|
||||
break;
|
||||
|
||||
case XbaeTraverseCellReason:
|
||||
DEBUG("XbaeTraverseCellReason");
|
||||
/* This ensure that whenever the user hits TAB, they go to the
|
||||
@ -1863,11 +1922,11 @@ dateCellFormat( Widget mw, XbaeMatrixModifyVerifyCallbackStruct *mvcbs, int do_y
|
||||
|
||||
if( changed )
|
||||
{
|
||||
sprintf( buf,"%2d/%2d\0\0", date.month, date.day );
|
||||
sprintf( buf,"%2d/%2d", date.month, date.day );
|
||||
XbaeMatrixSetCell( mw, row, col, buf );
|
||||
XbaeMatrixRefreshCell( mw, row, col );
|
||||
|
||||
sprintf( buf,"%4d\0", date.year );
|
||||
sprintf( buf,"%4d", date.year );
|
||||
XbaeMatrixSetCell( mw, row+1, col, buf );
|
||||
XbaeMatrixRefreshCell( mw, row+1, col );
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ initTransaction( Transaction * trans )
|
||||
trans->debit = 0x0;
|
||||
trans->credit = 0x0;
|
||||
|
||||
trans->num = NULL;
|
||||
trans->description = NULL;
|
||||
trans->memo = NULL;
|
||||
trans->action = NULL;
|
||||
trans->num = XtNewString("");
|
||||
trans->description = XtNewString("");
|
||||
trans->memo = XtNewString("");
|
||||
trans->action = XtNewString("");
|
||||
trans->catagory = 0;
|
||||
trans->reconciled = NREC;
|
||||
trans->damount = 0.0;
|
||||
@ -88,6 +88,7 @@ freeTransaction( Transaction *trans )
|
||||
XtFree(trans->num);
|
||||
XtFree(trans->description);
|
||||
XtFree(trans->memo);
|
||||
XtFree(trans->action);
|
||||
|
||||
initTransaction (trans); /* just in case someone looks up freed memory ... */
|
||||
_free(trans);
|
||||
|
56
src/XferBox.c
Normal file
56
src/XferBox.c
Normal file
@ -0,0 +1,56 @@
|
||||
/********************************************************************\
|
||||
* XferBox.c -- account transfers for xacc (X-Accountant) *
|
||||
* Copyright (C) 1997 Linas Vepstas *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
|
||||
#include "Data.h"
|
||||
#include "PopBox.h"
|
||||
#include "util.h"
|
||||
|
||||
/********************************************************************\
|
||||
* xferBox *
|
||||
* creates the xfer widget *
|
||||
* *
|
||||
* Args: parent - the parent of this window *
|
||||
* Return: PopBox - the xfer GUI structure *
|
||||
\********************************************************************/
|
||||
|
||||
PopBox *
|
||||
xferBox (Widget parent, Data *dayta)
|
||||
{
|
||||
PopBox *popGUI;
|
||||
Account * acc;
|
||||
int n;
|
||||
|
||||
popGUI = popBox (parent);
|
||||
|
||||
/* build the xfer menu out of account names */
|
||||
n = 0;
|
||||
acc = getAccount (dayta, n);
|
||||
while (acc) {
|
||||
AddPopBoxMenuItem (popGUI, acc->accountName);
|
||||
n++;
|
||||
acc = getAccount (dayta, n);
|
||||
}
|
||||
|
||||
return popGUI;
|
||||
}
|
||||
|
||||
/************************* END OF FILE ******************************/
|
@ -94,7 +94,7 @@ String fbRes[] = {
|
||||
"*recn*cellMarginWidth: 0",
|
||||
"*recn*cellMarginHeight: 0",
|
||||
/* combobox -- don't want the cell to be outlined */
|
||||
"*reg*actionbox*shadowThickness: 0",
|
||||
"*reg*popbox*shadowThickness: 0",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user