mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Auto-completion, bug fixes.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2400 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
52e00f615b
commit
31f35dd2f7
19
ChangeLog
19
ChangeLog
@ -1,3 +1,10 @@
|
||||
2000-06-02 Dave Peticolas <dave@krondo.com>
|
||||
|
||||
* src/register/splitreg.c: added functions for getting cell types
|
||||
and getting the locations for cell types.
|
||||
|
||||
* src/SplitLedger.c: add functionality for auto-completion
|
||||
|
||||
2000-06-02 Rob Browning <rlb@cs.utexas.edu>
|
||||
|
||||
* quite a few bugfixes to the automake stuff.
|
||||
@ -54,8 +61,7 @@
|
||||
acconfig.h - aclocal.m4 is now autogenerated, so use this instead.
|
||||
Various libtool files automagically added by libtool.
|
||||
src/examples/xacc-shell.c -> old/xacc-shell.c
|
||||
|
||||
|
||||
|
||||
* src/scm/startup.scm: load depend.scm here.
|
||||
|
||||
* src/scm/report/average-balance.scm: handle new possible #f
|
||||
@ -68,6 +74,15 @@
|
||||
|
||||
* src/scm/engine-utilities.scm: new file.
|
||||
|
||||
2000-05-31 Dave Peticolas <peticola@cs.ucdavis.edu>
|
||||
|
||||
* src/register/splitreg.c (configLabels): label the straight xfer
|
||||
and xfer to cells as 'Account', label the mirrored xfer as just
|
||||
'Transfer'.
|
||||
|
||||
* src/register/gnome/gnucash-header.c
|
||||
(gnucash_header_reconfigure): also redraw if the style changes.
|
||||
|
||||
2000-05-30 Dave Peticolas <peticola@cs.ucdavis.edu>
|
||||
|
||||
* src/register/quickfillcell.c: if a quickfill attempt fails,
|
||||
|
@ -83,8 +83,8 @@ exit(0);
|
||||
__DATA__
|
||||
|
||||
obj
|
||||
g-wrap-install
|
||||
Makefile
|
||||
Makefile.in
|
||||
Makefile.init
|
||||
config.cache
|
||||
config.log
|
||||
@ -109,32 +109,27 @@ stamp-h
|
||||
configure
|
||||
.deps
|
||||
.libs
|
||||
*.i
|
||||
gnucash.engine.i
|
||||
gnucash.pm
|
||||
gnucash-engine-perl5_wrap.c
|
||||
g-wrap-guile
|
||||
libgwrapguile.la
|
||||
libgwraprs.la
|
||||
gnc-autogen.h
|
||||
src/g-wrap/gnc.c
|
||||
src/g-wrap/gnc.h
|
||||
src/g-wrap/gnc.html
|
||||
src/guile/gnc.c
|
||||
src/guile/gnc.h
|
||||
src/guile/gnc.html
|
||||
src/guile/gnucash.c
|
||||
src/scm/bootstrap.scm
|
||||
src/swig/perl5/gnucash.engine_wrap.doc
|
||||
g-wrap.info
|
||||
lib/g-wrap/Makefile.in
|
||||
lib/g-wrap/rscheme/g-wrap-rs
|
||||
src/quotes/gnc-prices
|
||||
gtksheet*
|
||||
*.wrap
|
||||
*.orig
|
||||
*.rej
|
||||
src/reports/pathconfig.h
|
||||
*.moc
|
||||
*.gmo
|
||||
*.mo
|
||||
po/Makefile.in
|
||||
POTFILES
|
||||
cat-id-tbl.c
|
||||
gnucash.pot
|
||||
|
1898
po/gnucash.pot
1898
po/gnucash.pot
File diff suppressed because it is too large
Load Diff
@ -666,10 +666,6 @@ xaccLedgerDisplayClose (xaccLedgerDisplay *regData)
|
||||
if (!regData) return;
|
||||
acc = regData->leader;
|
||||
|
||||
/* Save any unsaved changes */
|
||||
if (xaccSRSaveRegEntry (regData->ledger, NULL))
|
||||
xaccSRRedrawRegEntry (regData->ledger);
|
||||
|
||||
xaccDestroySplitRegister (regData->ledger);
|
||||
|
||||
/* whether this is a single or multi-account window, remove it */
|
||||
|
1682
src/SplitLedger.c
1682
src/SplitLedger.c
File diff suppressed because it is too large
Load Diff
@ -96,11 +96,11 @@
|
||||
* The xaccSRSaveRegEntry() method will copy the contents
|
||||
* from the cursor to a split. The split/transaction
|
||||
* that is updated is the one associated with the current
|
||||
* cursor (register entry) position. If the current transaction
|
||||
* is different from newtrans, the current transaction will be
|
||||
* comitted. Pass in NULL for newtrans to force a commit.
|
||||
* The method returns GNC_T if the cursor was really saved,
|
||||
* i.e., it had been changed. Otherwise, it returns GNC_F.
|
||||
* cursor (register entry) position. If the do_commit flag
|
||||
* is set, the transaction will also be committed. If it is
|
||||
* the blank transaction, and the do_commit flag is set,
|
||||
* a refresh will result in a new blank transaction.
|
||||
* The method returns GNC_T if something was changed.
|
||||
*
|
||||
* The xaccSRRedrawRegEntry() method should be called soon
|
||||
* after the xaccSRSaveRegEntry() method. It checks the
|
||||
@ -161,9 +161,11 @@ void xaccSRCancelCursorTransChanges (SplitRegister *reg);
|
||||
void xaccSRLoadRegister (SplitRegister *reg, Split **slist,
|
||||
Account *default_source_acc);
|
||||
|
||||
gncBoolean xaccSRSaveRegEntry (SplitRegister *reg, Transaction *newtrans);
|
||||
gncBoolean xaccSRSaveRegEntry (SplitRegister *reg, gncBoolean do_commit);
|
||||
void xaccSRRedrawRegEntry (SplitRegister *reg);
|
||||
|
||||
void xaccSRLoadXferCells (SplitRegister *reg, Account *base_account);
|
||||
|
||||
gncBoolean xaccSRHasPendingChanges (SplitRegister *reg);
|
||||
|
||||
#endif /* __XACC_SPLIT_LEDGER_H__ */
|
||||
|
@ -170,12 +170,18 @@ Split * xaccAccountGetSplit (Account *acc, int i);
|
||||
Split ** xaccAccountGetSplitList (Account *acc);
|
||||
int xaccAccountGetNumSplits (Account *acc);
|
||||
|
||||
/* WAKE UP!
|
||||
/* The xaccAccountGetFullName routine returns the fully qualified name
|
||||
* of the account using the given separator char. The name must be freed
|
||||
* after use. The fully qualified name of an account is the concatenation
|
||||
* of the names of the account and all its ancestor accounts starting with
|
||||
* the topmost account and ending with the given account. Each name is
|
||||
* separated by the given character.
|
||||
*
|
||||
* WAKE UP!
|
||||
* Unlike all other gets, the string returned by xaccAccountGetFullName()
|
||||
* must be freed by you the user !!!
|
||||
* hack alert -- can someone document what this routine does, and also,
|
||||
* since it breaks the rule of string allocation, maybe this routine
|
||||
* should not be in this library, but some utility library ???
|
||||
* must be freed by you the user !!!
|
||||
* hack alert -- since it breaks the rule of string allocation, maybe this
|
||||
* routine should not be in this library, but some utility library?
|
||||
*/
|
||||
char * xaccAccountGetFullName (Account *, const char separator);
|
||||
|
||||
@ -205,7 +211,7 @@ gncBoolean xaccAccountHasAncestor (Account *, Account * ancestor);
|
||||
*
|
||||
* The xaccClearMark will find the topmost group, and clear the mark in
|
||||
* the entire group tree.
|
||||
* The xaccClearMarkDown will clear the mark inly in this and in
|
||||
* The xaccClearMarkDown will clear the mark only in this and in
|
||||
* sub-accounts.
|
||||
*/
|
||||
short xaccAccountGetMark (Account *acc);
|
||||
|
@ -1852,7 +1852,7 @@ static int
|
||||
writeTSDate( int fd, Timespec *ts)
|
||||
{
|
||||
int err=0;
|
||||
int tmp;
|
||||
long int tmp;
|
||||
long long longtmp;
|
||||
|
||||
/* write 64 bits to file format */
|
||||
@ -1864,8 +1864,8 @@ writeTSDate( int fd, Timespec *ts)
|
||||
|
||||
tmp = ts->tv_nsec;
|
||||
XACC_FLIP_INT (tmp);
|
||||
err = write( fd, &tmp, sizeof(int) );
|
||||
if( err != sizeof(int) )
|
||||
err = write( fd, &tmp, sizeof(long int) );
|
||||
if( err != sizeof(long int) )
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
|
@ -289,10 +289,10 @@ const char * xaccTransFindCommonCurrency (Transaction *trans);
|
||||
* currency and a common security. If the desired match is the
|
||||
* security, a simple string match won't reveal this fact.
|
||||
*
|
||||
* This routine is useful in dealing
|
||||
* with currency trading accounts and/or with "stock boxes", where
|
||||
* transaction have in common. This routine is useful in dealing
|
||||
* securities of differing types are moved across accounts.
|
||||
* This routine is useful in dealing with currency trading accounts
|
||||
* and/or with "stock boxes", where transaction have a security in
|
||||
* common. This routine is useful in dealing with securities of
|
||||
* differing types as they are moved across accounts.
|
||||
*/
|
||||
const char * xaccTransIsCommonCurrency (Transaction *trans,
|
||||
const char * currency);
|
||||
|
@ -36,7 +36,7 @@
|
||||
* routines that perform sub-atomic updates of the accounting
|
||||
* structures. If these routines are not used properly, they
|
||||
* can result in inconsistent, unbalanced accounting structures.
|
||||
* In other words, thier use is dangerous, and thier use outside
|
||||
* In other words, their use is dangerous, and their use outside
|
||||
* of the scope of the engine is forbidden.
|
||||
*
|
||||
*/
|
||||
|
@ -335,7 +335,6 @@ guid_init()
|
||||
/* time in secs and clock ticks */
|
||||
bytes += init_from_time();
|
||||
|
||||
fprintf(stderr, "guid_init got %u bytes.\n", bytes);
|
||||
if (bytes < THRESHOLD)
|
||||
fprintf(stderr,
|
||||
"WARNING: guid_init only got %u bytes.\n"
|
||||
|
450
src/engine/guid/guid.c
Normal file
450
src/engine/guid/guid.c
Normal file
@ -0,0 +1,450 @@
|
||||
/********************************************************************\
|
||||
* guid.c -- globally unique ID implementation *
|
||||
* Copyright (C) 2000 Dave Peticolas <peticola@cs.ucdavis.edu> *
|
||||
* *
|
||||
* 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, contact: *
|
||||
* *
|
||||
* Free Software Foundation Voice: +1-617-542-5942 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "guid.h"
|
||||
#include "md5.h"
|
||||
|
||||
# ifndef P_tmpdir
|
||||
# define P_tmpdir "/tmp"
|
||||
# endif
|
||||
|
||||
|
||||
/** Constants *******************************************************/
|
||||
#define GUID_TRUE (0 == 0)
|
||||
#define GUID_FALSE (! GUID_TRUE)
|
||||
#define BLOCKSIZE 4096
|
||||
#define THRESHOLD (2 * BLOCKSIZE)
|
||||
|
||||
|
||||
/** Static global variables *****************************************/
|
||||
static int guid_initialized = GUID_FALSE;
|
||||
static struct md5_ctx guid_context;
|
||||
|
||||
|
||||
/** Function implementations ****************************************/
|
||||
|
||||
/* This code is based on code in md5.c in GNU textutils. */
|
||||
static size_t
|
||||
init_from_stream(FILE *stream, size_t max_size)
|
||||
{
|
||||
char buffer[BLOCKSIZE + 72];
|
||||
size_t sum, block_size, total;
|
||||
|
||||
if (max_size <= 0)
|
||||
return 0;
|
||||
|
||||
total = 0;
|
||||
|
||||
/* Iterate over file contents. */
|
||||
while (1)
|
||||
{
|
||||
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||
* computation function processes the whole buffer so that with the
|
||||
* next round of the loop another block can be read. */
|
||||
size_t n;
|
||||
sum = 0;
|
||||
|
||||
if (max_size < BLOCKSIZE)
|
||||
block_size = max_size;
|
||||
else
|
||||
block_size = BLOCKSIZE;
|
||||
|
||||
/* Read block. Take care for partial reads. */
|
||||
do
|
||||
{
|
||||
n = fread (buffer + sum, 1, block_size - sum, stream);
|
||||
|
||||
sum += n;
|
||||
}
|
||||
while (sum < block_size && n != 0);
|
||||
|
||||
max_size -= sum;
|
||||
|
||||
if (n == 0 && ferror (stream))
|
||||
return total;
|
||||
|
||||
/* If end of file or max_size is reached, end the loop. */
|
||||
if ((n == 0) || (max_size == 0))
|
||||
break;
|
||||
|
||||
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||
* BLOCKSIZE % 64 == 0 */
|
||||
md5_process_block (buffer, BLOCKSIZE, &guid_context);
|
||||
|
||||
total += sum;
|
||||
}
|
||||
|
||||
/* Add the last bytes if necessary. */
|
||||
if (sum > 0)
|
||||
{
|
||||
md5_process_bytes (buffer, sum, &guid_context);
|
||||
total += sum;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static size_t
|
||||
init_from_file(const char *filename, size_t max_size)
|
||||
{
|
||||
struct stat stats;
|
||||
size_t total = 0;
|
||||
FILE *fp;
|
||||
|
||||
if (stat(filename, &stats) == 0)
|
||||
{
|
||||
md5_process_bytes(&stats, sizeof(stats), &guid_context);
|
||||
total += sizeof(stats);
|
||||
}
|
||||
|
||||
if (max_size <= 0)
|
||||
return total;
|
||||
|
||||
fp = fopen (filename, "r");
|
||||
if (fp == NULL)
|
||||
return total;
|
||||
|
||||
total += init_from_stream(fp, max_size);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static size_t
|
||||
init_from_dir(const char *dirname, unsigned int max_files)
|
||||
{
|
||||
char filename[1024];
|
||||
struct dirent *de;
|
||||
struct stat stats;
|
||||
size_t total;
|
||||
int result;
|
||||
DIR *dir;
|
||||
|
||||
if (max_files <= 0)
|
||||
return 0;
|
||||
|
||||
dir = opendir (dirname);
|
||||
if (dir == NULL)
|
||||
return 0;
|
||||
|
||||
total = 0;
|
||||
|
||||
do
|
||||
{
|
||||
de = readdir(dir);
|
||||
if (de == NULL)
|
||||
break;
|
||||
|
||||
md5_process_bytes(de, sizeof(struct dirent), &guid_context);
|
||||
total += sizeof(struct dirent);
|
||||
|
||||
result = snprintf(filename, sizeof(filename),
|
||||
"%s/%s", dirname, de->d_name);
|
||||
if ((result < 0) || (result >= sizeof(filename)))
|
||||
continue;
|
||||
|
||||
if (stat(filename, &stats) != 0)
|
||||
continue;
|
||||
md5_process_bytes(&stats, sizeof(stats), &guid_context);
|
||||
total += sizeof(stats);
|
||||
|
||||
max_files--;
|
||||
} while (max_files > 0);
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static size_t
|
||||
init_from_time()
|
||||
{
|
||||
size_t total;
|
||||
time_t t_time;
|
||||
clock_t clocks;
|
||||
struct tms tms_buf;
|
||||
|
||||
total = 0;
|
||||
|
||||
t_time = time(NULL);
|
||||
md5_process_bytes(&t_time, sizeof(t_time), &guid_context);
|
||||
total += sizeof(t_time);
|
||||
|
||||
clocks = times(&tms_buf);
|
||||
md5_process_bytes(&clocks, sizeof(clocks), &guid_context);
|
||||
md5_process_bytes(&tms_buf, sizeof(tms_buf), &guid_context);
|
||||
total += sizeof(clocks) + sizeof(tms_buf);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
guid_init()
|
||||
{
|
||||
size_t bytes = 0;
|
||||
|
||||
md5_init_ctx(&guid_context);
|
||||
|
||||
/* files */
|
||||
{
|
||||
const char * files[] =
|
||||
{ "/dev/urandom",
|
||||
"/etc/passwd",
|
||||
"/proc/loadavg",
|
||||
"/proc/meminfo",
|
||||
"/proc/net/dev",
|
||||
"/proc/rtc",
|
||||
"/proc/self/environ",
|
||||
"/proc/self/stat",
|
||||
"/proc/stat",
|
||||
"/proc/uptime",
|
||||
"/dev/urandom", /* once more for good measure :) */
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; files[i] != NULL; i++)
|
||||
bytes += init_from_file(files[i], BLOCKSIZE);
|
||||
}
|
||||
|
||||
/* directories */
|
||||
{
|
||||
const char * dirname;
|
||||
const char * dirs[] =
|
||||
{
|
||||
"/proc",
|
||||
P_tmpdir,
|
||||
"/var/lock",
|
||||
"/var/log",
|
||||
"/var/mail",
|
||||
"/var/spool/mail",
|
||||
"/var/run",
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; dirs[i] != NULL; i++)
|
||||
bytes += init_from_dir(dirs[i], 32);
|
||||
|
||||
dirname = getenv("HOME");
|
||||
if (dirname != NULL)
|
||||
bytes += init_from_dir(dirname, 32);
|
||||
}
|
||||
|
||||
/* process and parent ids */
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = getpid();
|
||||
md5_process_bytes(&pid, sizeof(pid), &guid_context);
|
||||
bytes += sizeof(pid);
|
||||
|
||||
pid = getppid();
|
||||
md5_process_bytes(&pid, sizeof(pid), &guid_context);
|
||||
bytes += sizeof(pid);
|
||||
}
|
||||
|
||||
/* user info */
|
||||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *s;
|
||||
|
||||
s = getlogin();
|
||||
if (s != NULL)
|
||||
{
|
||||
md5_process_bytes(s, strlen(s), &guid_context);
|
||||
bytes += strlen(s);
|
||||
}
|
||||
|
||||
uid = getuid();
|
||||
md5_process_bytes(&uid, sizeof(uid), &guid_context);
|
||||
bytes += sizeof(uid);
|
||||
|
||||
gid = getgid();
|
||||
md5_process_bytes(&gid, sizeof(gid), &guid_context);
|
||||
bytes += sizeof(gid);
|
||||
}
|
||||
|
||||
/* host info */
|
||||
{
|
||||
char string[1024];
|
||||
|
||||
gethostname(string, sizeof(string));
|
||||
md5_process_bytes(string, sizeof(string), &guid_context);
|
||||
bytes += sizeof(string);
|
||||
|
||||
getdomainname(string, sizeof(string));
|
||||
md5_process_bytes(string, sizeof(string), &guid_context);
|
||||
bytes += sizeof(string);
|
||||
}
|
||||
|
||||
/* plain old random */
|
||||
{
|
||||
int n, i;
|
||||
|
||||
srand((unsigned int) time(NULL));
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
n = rand();
|
||||
|
||||
md5_process_bytes(&n, sizeof(n), &guid_context);
|
||||
bytes += sizeof(n);
|
||||
}
|
||||
}
|
||||
|
||||
/* time in secs and clock ticks */
|
||||
bytes += init_from_time();
|
||||
|
||||
if (bytes < THRESHOLD)
|
||||
fprintf(stderr,
|
||||
"WARNING: guid_init only got %u bytes.\n"
|
||||
"The identifiers might not be very random.\n", bytes);
|
||||
|
||||
guid_initialized = GUID_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
guid_init_with_salt(const void *salt, size_t salt_len)
|
||||
{
|
||||
guid_init();
|
||||
|
||||
md5_process_bytes(salt, salt_len, &guid_context);
|
||||
}
|
||||
|
||||
void
|
||||
guid_init_only_salt(const void *salt, size_t salt_len)
|
||||
{
|
||||
md5_init_ctx(&guid_context);
|
||||
|
||||
md5_process_bytes(salt, salt_len, &guid_context);
|
||||
|
||||
guid_initialized = GUID_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
guid_new(GUID *guid)
|
||||
{
|
||||
struct md5_ctx ctx;
|
||||
|
||||
if (guid == NULL)
|
||||
return;
|
||||
|
||||
if (!guid_initialized)
|
||||
guid_init();
|
||||
|
||||
/* make the id */
|
||||
ctx = guid_context;
|
||||
md5_finish_ctx(&ctx, guid->data);
|
||||
|
||||
/* update the global context */
|
||||
init_from_time();
|
||||
}
|
||||
|
||||
/* needs 32 bytes exactly, doesn't print a null char */
|
||||
static void
|
||||
encode_md5_data(const unsigned char *data, char *buffer)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
for (count = 0; count < 16; count++, buffer += 2)
|
||||
sprintf(buffer, "%02x", data[count]);
|
||||
}
|
||||
|
||||
/* returns true if the first 32 bytes of buffer encode
|
||||
* a hex number. returns false otherwise. Decoded number
|
||||
* is packed into data in little endian order. */
|
||||
static int
|
||||
decode_md5_string(const char *string, unsigned char *data)
|
||||
{
|
||||
unsigned char n1, n2;
|
||||
size_t count;
|
||||
char c1, c2;
|
||||
|
||||
if (string == NULL)
|
||||
return GUID_FALSE;
|
||||
|
||||
for (count = 0; count < 16; count++)
|
||||
{
|
||||
c1 = tolower(string[2 * count]);
|
||||
if (!isxdigit(c1))
|
||||
return GUID_FALSE;
|
||||
|
||||
c2 = tolower(string[2 * count + 1]);
|
||||
if (!isxdigit(c2))
|
||||
return GUID_FALSE;
|
||||
|
||||
if (isdigit(c1))
|
||||
n1 = c1 - '0';
|
||||
else
|
||||
n1 = c1 - 'a' + 10;
|
||||
|
||||
if (isdigit(c2))
|
||||
n2 = c2 - '0';
|
||||
else
|
||||
n2 = c2 - 'a' + 10;
|
||||
|
||||
if (data != NULL)
|
||||
data[count] = (n1 << 4) | n2;
|
||||
}
|
||||
|
||||
return GUID_TRUE;
|
||||
}
|
||||
|
||||
char *
|
||||
guid_to_string(const GUID * guid)
|
||||
{
|
||||
char *string = malloc(GUID_ENCODING_LENGTH+1);
|
||||
if (!string) return NULL;
|
||||
|
||||
encode_md5_data(guid->data, string);
|
||||
|
||||
string[GUID_ENCODING_LENGTH] = '\0';
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int
|
||||
string_to_guid(const char * string, GUID * guid)
|
||||
{
|
||||
return decode_md5_string(string, (guid != NULL) ? guid->data : NULL);
|
||||
}
|
@ -2119,7 +2119,7 @@ recordCB(GtkWidget *w, gpointer data)
|
||||
|
||||
trans = xaccSRGetCurrentTrans(regData->ledger->ledger);
|
||||
|
||||
really_saved = xaccSRSaveRegEntry(regData->ledger->ledger, NULL);
|
||||
really_saved = xaccSRSaveRegEntry(regData->ledger->ledger, GNC_T);
|
||||
if (!really_saved)
|
||||
return;
|
||||
|
||||
@ -2388,10 +2388,10 @@ cancelCB(GtkWidget *w, gpointer data)
|
||||
static void
|
||||
gnc_register_check_close(RegWindow *regData)
|
||||
{
|
||||
unsigned int changed;
|
||||
gncBoolean pending_changes;
|
||||
|
||||
changed = xaccSplitRegisterGetChangeFlag(regData->ledger->ledger);
|
||||
if (changed)
|
||||
pending_changes = xaccSRHasPendingChanges(regData->ledger->ledger);
|
||||
if (pending_changes)
|
||||
{
|
||||
if (gnc_verify_dialog_parented
|
||||
(GTK_WINDOW(regData->window), TRANS_CHANGED_MSG, GNC_T))
|
||||
|
@ -46,7 +46,7 @@ SWIG_INPUT_HDRS := \
|
||||
## aren't named lib*.so...
|
||||
install-data-local: libgncswig.la
|
||||
cd ${perllibdir} && rm -f gnucash.so
|
||||
cd ${perllibdir} && ln libgncswig.so gnucash.so
|
||||
cd ${perllibdir} && ln -s libgncswig.so gnucash.so
|
||||
|
||||
uninstall-local:
|
||||
rm -f ${perllibdir}/gnucash.so
|
||||
|
@ -431,7 +431,7 @@ maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
install-data-local: libgncswig.la
|
||||
cd ${perllibdir} && rm -f gnucash.so
|
||||
cd ${perllibdir} && ln libgncswig.so gnucash.so
|
||||
cd ${perllibdir} && ln -s libgncswig.so gnucash.so
|
||||
|
||||
uninstall-local:
|
||||
rm -f ${perllibdir}/gnucash.so
|
||||
|
@ -162,4 +162,15 @@ xaccBasicCellGetHelp (BasicCell *cell)
|
||||
return cell->get_help_value(cell);
|
||||
}
|
||||
|
||||
/* ===================================================== */
|
||||
|
||||
void
|
||||
xaccBasicCellSetChanged (BasicCell *cell, gncBoolean changed)
|
||||
{
|
||||
if (cell == NULL)
|
||||
return;
|
||||
|
||||
cell->changed = changed ? 0xffffffff : 0;
|
||||
}
|
||||
|
||||
/* ================== end of file ====================== */
|
||||
|
@ -268,5 +268,7 @@ void xaccSetBasicCellValue (BasicCell *, const char *);
|
||||
void xaccSetBasicCellBlankHelp (BasicCell *, const char *);
|
||||
char * xaccBasicCellGetHelp (BasicCell *);
|
||||
|
||||
void xaccBasicCellSetChanged (BasicCell *, gncBoolean);
|
||||
|
||||
#endif /* __XACC_BASIC_CELL_H__ */
|
||||
/* ------------------ end of file ---------------------- */
|
||||
|
@ -124,7 +124,7 @@ struct _CellBlock {
|
||||
* (exit_r, exit_c) is the last cell of this tab group.
|
||||
*/
|
||||
|
||||
/* the last-reneter row and column should contain the very last
|
||||
/* the last-reenter row and column should contain the very last
|
||||
* cell when the cursor was traversed out of. They determine
|
||||
* the first cell that will be entered (since the first follows
|
||||
* the last).
|
||||
|
@ -227,6 +227,7 @@ gnucash_header_reconfigure (GnucashHeader *header)
|
||||
GnomeCanvas *canvas;
|
||||
GtkWidget *widget;
|
||||
GnucashSheet *sheet;
|
||||
SheetBlockStyle *old_style;
|
||||
|
||||
g_return_if_fail (header != NULL);
|
||||
g_return_if_fail (GNUCASH_IS_HEADER (header));
|
||||
@ -234,6 +235,7 @@ gnucash_header_reconfigure (GnucashHeader *header)
|
||||
canvas = GNOME_CANVAS_ITEM(header)->canvas;
|
||||
widget = GTK_WIDGET (header->sheet);
|
||||
sheet = GNUCASH_SHEET(header->sheet);
|
||||
old_style = header->style;
|
||||
|
||||
header->style = header->sheet->cursor_style[header->type];
|
||||
|
||||
@ -250,7 +252,8 @@ gnucash_header_reconfigure (GnucashHeader *header)
|
||||
w = MAX (widget->allocation.width, header->style->dimensions->width);
|
||||
h = header->style->dimensions->height;
|
||||
|
||||
if (header->height != h || header->width != w) {
|
||||
if (header->height != h || header->width != w ||
|
||||
header->style != old_style) {
|
||||
header->height = h;
|
||||
header->width = w;
|
||||
|
||||
|
@ -1,103 +0,0 @@
|
||||
/* XPM */
|
||||
static char * left_arrow_small_xpm[] = {
|
||||
"13 14 86 1",
|
||||
" c None",
|
||||
". c #AC9B8E",
|
||||
"+ c #8D5C3F",
|
||||
"@ c #A26A47",
|
||||
"# c #8F603E",
|
||||
"$ c #432214",
|
||||
"% c #8A4629",
|
||||
"& c #9E5A39",
|
||||
"* c #B6754F",
|
||||
"= c #8A5D42",
|
||||
"- c #974F31",
|
||||
"; c #A85D3A",
|
||||
"> c #AC603F",
|
||||
", c #B36D48",
|
||||
"' c #BA7A56",
|
||||
") c #684937",
|
||||
"! c #975135",
|
||||
"~ c #B66C48",
|
||||
"{ c #C57653",
|
||||
"] c #C27552",
|
||||
"^ c #C37650",
|
||||
"/ c #CB805C",
|
||||
"( c #C58664",
|
||||
"_ c #8F5036",
|
||||
": c #BE704D",
|
||||
"< c #CE825B",
|
||||
"[ c #D38560",
|
||||
"} c #D58761",
|
||||
"| c #D58862",
|
||||
"1 c #D78A63",
|
||||
"2 c #DE9471",
|
||||
"3 c #C98F73",
|
||||
"4 c #7F5846",
|
||||
"5 c #9D6F58",
|
||||
"6 c #C97B56",
|
||||
"7 c #D88A65",
|
||||
"8 c #DB8D67",
|
||||
"9 c #E19069",
|
||||
"0 c #E3946D",
|
||||
"a c #EA9B75",
|
||||
"b c #EBA47F",
|
||||
"c c #E59A75",
|
||||
"d c #AD6B4E",
|
||||
"e c #7D4E3A",
|
||||
"f c #E3B29A",
|
||||
"g c #D68963",
|
||||
"h c #E1916C",
|
||||
"i c #E79870",
|
||||
"j c #EA9E79",
|
||||
"k c #F0A682",
|
||||
"l c #E7A37F",
|
||||
"m c #BD7656",
|
||||
"n c #693924",
|
||||
"o c #26170F",
|
||||
"p c #040302",
|
||||
"q c #000000",
|
||||
"r c #E7B097",
|
||||
"s c #E3936A",
|
||||
"t c #ECA179",
|
||||
"u c #EFA781",
|
||||
"v c #EA9F7C",
|
||||
"w c #C77E5E",
|
||||
"x c #7E4833",
|
||||
"y c #3C2118",
|
||||
"z c #0B0604",
|
||||
"A c #E9AC90",
|
||||
"B c #EEA47F",
|
||||
"C c #EBA27D",
|
||||
"D c #BF7859",
|
||||
"E c #844830",
|
||||
"F c #402318",
|
||||
"G c #130B07",
|
||||
"H c #B09488",
|
||||
"I c #EFA685",
|
||||
"J c #CE8361",
|
||||
"K c #87462F",
|
||||
"L c #3C1F13",
|
||||
"M c #0F0805",
|
||||
"N c #E5BAA8",
|
||||
"O c #9F5E43",
|
||||
"P c #4F271B",
|
||||
"Q c #170D09",
|
||||
"R c #020100",
|
||||
"S c #684A3D",
|
||||
"T c #1B0F0A",
|
||||
"U c #050302",
|
||||
". ",
|
||||
"+@# ",
|
||||
"$%&*= ",
|
||||
" -;>,') ",
|
||||
" !~{]^/( ",
|
||||
" _:<[}|1234 ",
|
||||
" 567890abcde ",
|
||||
" fghijklmnopq",
|
||||
" rstuvwxyzqq ",
|
||||
" ABCDEFGqq ",
|
||||
"HIJKLMqq ",
|
||||
"NOPQRq ",
|
||||
"STUq ",
|
||||
" q "};
|
@ -101,30 +101,6 @@ static SplitRegisterColors reg_colors = {
|
||||
};
|
||||
|
||||
|
||||
/* utility defines for cell configuration data */
|
||||
#define DATE_CELL 0
|
||||
#define NUM_CELL 1
|
||||
#define DESC_CELL 2
|
||||
#define RECN_CELL 3
|
||||
#define SHRS_CELL 4
|
||||
#define BALN_CELL 5
|
||||
#define ACTN_CELL 6
|
||||
#define XFRM_CELL 7
|
||||
#define XTO_CELL 8
|
||||
#define MEMO_CELL 9
|
||||
#define CRED_CELL 10
|
||||
#define DEBT_CELL 11
|
||||
#define PRIC_CELL 12
|
||||
#define VALU_CELL 13
|
||||
|
||||
/* NCRED & NDEBT handle minus the usual quantities */
|
||||
#define NCRED_CELL 14
|
||||
#define NDEBT_CELL 15
|
||||
|
||||
/* MXFRM is the "mirrored" transfer-from account */
|
||||
#define MXFRM_CELL 16
|
||||
|
||||
|
||||
#define DATE_CELL_WIDTH 11
|
||||
#define NUM_CELL_WIDTH 7
|
||||
#define ACTN_CELL_WIDTH 7
|
||||
@ -203,9 +179,9 @@ configLabels (SplitRegister *reg)
|
||||
LABEL (SHRS, TOTAL_SHARES_STR);
|
||||
LABEL (BALN, BALN_STR);
|
||||
LABEL (ACTN, ACTION_STR);
|
||||
LABEL (XFRM, XFRM_STR);
|
||||
LABEL (MXFRM, XFRM_STR);
|
||||
LABEL (XTO, XFTO_STR);
|
||||
LABEL (XFRM, ACCOUNT_STR);
|
||||
LABEL (MXFRM, TRANSFER_STR);
|
||||
LABEL (XTO, ACCOUNT_STR);
|
||||
LABEL (MEMO, MEMO_STR);
|
||||
LABEL (CRED, CREDIT_STR);
|
||||
LABEL (DEBT, DEBIT_STR);
|
||||
@ -1388,6 +1364,198 @@ xaccSplitRegisterGetCursorTypeRowCol (SplitRegister *reg,
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
CellType
|
||||
sr_cell_type (SplitRegister *reg, void * cell)
|
||||
{
|
||||
if (cell == reg->dateCell)
|
||||
return DATE_CELL;
|
||||
|
||||
if (cell == reg->numCell)
|
||||
return NUM_CELL;
|
||||
|
||||
if (cell == reg->descCell)
|
||||
return DESC_CELL;
|
||||
|
||||
if (cell == reg->recnCell)
|
||||
return RECN_CELL;
|
||||
|
||||
if (cell == reg->shrsCell)
|
||||
return SHRS_CELL;
|
||||
|
||||
if (cell == reg->balanceCell)
|
||||
return BALN_CELL;
|
||||
|
||||
if (cell == reg->actionCell)
|
||||
return ACTN_CELL;
|
||||
|
||||
if (cell == reg->xfrmCell)
|
||||
return XFRM_CELL;
|
||||
|
||||
if (cell == reg->mxfrmCell)
|
||||
return MXFRM_CELL;
|
||||
|
||||
if (cell == reg->xtoCell)
|
||||
return XTO_CELL;
|
||||
|
||||
if (cell == reg->memoCell)
|
||||
return MEMO_CELL;
|
||||
|
||||
if (cell == reg->creditCell)
|
||||
return CRED_CELL;
|
||||
|
||||
if (cell == reg->debitCell)
|
||||
return DEBT_CELL;
|
||||
|
||||
if (cell == reg->priceCell)
|
||||
return PRIC_CELL;
|
||||
|
||||
if (cell == reg->valueCell)
|
||||
return VALU_CELL;
|
||||
|
||||
if (cell == reg->ncreditCell)
|
||||
return NCRED_CELL;
|
||||
|
||||
if (cell == reg->ndebitCell)
|
||||
return NDEBT_CELL;
|
||||
|
||||
return NO_CELL;
|
||||
}
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
CellType
|
||||
xaccSplitRegisterGetCellType (SplitRegister *reg)
|
||||
{
|
||||
Table *table;
|
||||
|
||||
if (reg == NULL)
|
||||
return NO_CELL;
|
||||
|
||||
table = reg->table;
|
||||
if (table == NULL)
|
||||
return NO_CELL;
|
||||
|
||||
return xaccSplitRegisterGetCellTypeRowCol(reg,
|
||||
table->current_cursor_phys_row,
|
||||
table->current_cursor_phys_col);
|
||||
}
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
static BasicCell *
|
||||
sr_current_cell (SplitRegister *reg)
|
||||
{
|
||||
Table *table;
|
||||
Locator *locator;
|
||||
CellBlock *cellblock;
|
||||
int phys_row, phys_col;
|
||||
int virt_row, virt_col;
|
||||
int cell_row, cell_col;
|
||||
|
||||
if (reg == NULL)
|
||||
return NULL;
|
||||
|
||||
table = reg->table;
|
||||
if (table == NULL)
|
||||
return NULL;
|
||||
|
||||
phys_row = table->current_cursor_phys_row;
|
||||
phys_col = table->current_cursor_phys_col;
|
||||
|
||||
if ((phys_row < 0) || (phys_row >= table->num_phys_rows) ||
|
||||
(phys_col < 0) || (phys_col >= table->num_phys_cols))
|
||||
return NULL;
|
||||
|
||||
locator = table->locators[phys_row][phys_col];
|
||||
|
||||
virt_row = locator->virt_row;
|
||||
virt_col = locator->virt_col;
|
||||
cell_row = locator->phys_row_offset;
|
||||
cell_col = locator->phys_col_offset;
|
||||
|
||||
cellblock = table->handlers[virt_row][virt_col];
|
||||
|
||||
return cellblock->cells[cell_row][cell_col];
|
||||
}
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
CellType
|
||||
xaccSplitRegisterGetCellTypeRowCol (SplitRegister *reg,
|
||||
int phys_row, int phys_col)
|
||||
{
|
||||
BasicCell *cell;
|
||||
|
||||
cell = sr_current_cell (reg);
|
||||
if (cell == NULL)
|
||||
return NO_CELL;
|
||||
|
||||
return sr_cell_type (reg, cell);
|
||||
}
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
gncBoolean
|
||||
xaccSplitRegisterGetCellRowCol (SplitRegister *reg, CellType cell_type,
|
||||
int *p_phys_row, int *p_phys_col)
|
||||
{
|
||||
Table *table;
|
||||
Locator *locator;
|
||||
CellBlock *cellblock;
|
||||
int phys_row, phys_col;
|
||||
int virt_row, virt_col;
|
||||
int cell_row, cell_col;
|
||||
|
||||
if (reg == NULL)
|
||||
return GNC_F;
|
||||
|
||||
table = reg->table;
|
||||
if (table == NULL)
|
||||
return GNC_F;
|
||||
|
||||
phys_row = table->current_cursor_phys_row;
|
||||
phys_col = table->current_cursor_phys_col;
|
||||
|
||||
if ((phys_row < 0) || (phys_row >= table->num_phys_rows) ||
|
||||
(phys_col < 0) || (phys_col >= table->num_phys_cols))
|
||||
return GNC_F;
|
||||
|
||||
locator = table->locators[phys_row][phys_col];
|
||||
|
||||
virt_row = locator->virt_row;
|
||||
virt_col = locator->virt_col;
|
||||
|
||||
cellblock = table->handlers[virt_row][virt_col];
|
||||
|
||||
for (cell_row = 0; cell_row < cellblock->numRows; cell_row++)
|
||||
for (cell_col = 0; cell_col < cellblock->numCols; cell_col++)
|
||||
{
|
||||
BasicCell *cell = cellblock->cells[cell_row][cell_col];
|
||||
|
||||
if (sr_cell_type (reg, cell) == cell_type)
|
||||
{
|
||||
RevLocator *rev_locator;
|
||||
|
||||
rev_locator = table->rev_locators[virt_row][virt_col];
|
||||
|
||||
phys_row = rev_locator->phys_row + cell_row;
|
||||
phys_col = rev_locator->phys_col + cell_col;
|
||||
|
||||
if (p_phys_row != NULL)
|
||||
*p_phys_row = phys_row;
|
||||
|
||||
if (p_phys_col != NULL)
|
||||
*p_phys_col = phys_col;
|
||||
|
||||
return GNC_T;
|
||||
}
|
||||
}
|
||||
|
||||
return GNC_F;
|
||||
}
|
||||
|
||||
/* ============================================== */
|
||||
|
||||
SplitRegisterBuffer *
|
||||
xaccMallocSplitRegisterBuffer ()
|
||||
{
|
||||
|
@ -82,6 +82,33 @@ typedef enum
|
||||
|
||||
#define REG_TYPE_MASK 0xff
|
||||
|
||||
/* These values are used to identify the cells in the register. */
|
||||
typedef enum
|
||||
{
|
||||
NO_CELL = -1,
|
||||
DATE_CELL = 0,
|
||||
NUM_CELL = 1,
|
||||
DESC_CELL = 2,
|
||||
RECN_CELL = 3,
|
||||
SHRS_CELL = 4,
|
||||
BALN_CELL = 5,
|
||||
ACTN_CELL = 6,
|
||||
XFRM_CELL = 7,
|
||||
XTO_CELL = 8,
|
||||
MEMO_CELL = 9,
|
||||
CRED_CELL = 10,
|
||||
DEBT_CELL = 11,
|
||||
PRIC_CELL = 12,
|
||||
VALU_CELL = 13,
|
||||
|
||||
/* NCRED & NDEBT handle minus the usual quantities */
|
||||
NCRED_CELL = 14,
|
||||
NDEBT_CELL = 15,
|
||||
|
||||
/* MXFRM is the "mirrored" transfer-from account */
|
||||
MXFRM_CELL = 16
|
||||
} CellType;
|
||||
|
||||
/*
|
||||
* enumerated display styles
|
||||
* REG_SINGLE_LINE -- show one line per transaction
|
||||
@ -236,9 +263,26 @@ void xaccSplitRegisterClearChangeFlag (SplitRegister *reg);
|
||||
|
||||
/* Returns the type of the current cursor */
|
||||
CursorType xaccSplitRegisterGetCursorType (SplitRegister *reg);
|
||||
|
||||
/* Returns the type of the cursor at the given virtual row and column. */
|
||||
CursorType xaccSplitRegisterGetCursorTypeRowCol (SplitRegister *reg,
|
||||
int virt_row,
|
||||
int virt_col);
|
||||
/* Returns the type of the current cell */
|
||||
CellType xaccSplitRegisterGetCellType (SplitRegister *reg);
|
||||
|
||||
/* Returns the type of the cell at the given physical row and column. */
|
||||
CellType xaccSplitRegisterGetCellTypeRowCol (SplitRegister *reg,
|
||||
int phys_row,
|
||||
int phys_col);
|
||||
|
||||
/* Returns the physical row and column in the current cursor of the
|
||||
* given cell using the pointer values. The function returns true if
|
||||
* the given cell type is in the current cursor, false otherwise. */
|
||||
gncBoolean xaccSplitRegisterGetCellRowCol (SplitRegister *reg,
|
||||
CellType cell_type,
|
||||
int *p_phys_row,
|
||||
int *p_phys_col);
|
||||
|
||||
/* Functions for working with split register buffers */
|
||||
SplitRegisterBuffer * xaccMallocSplitRegisterBuffer ();
|
||||
|
@ -1275,12 +1275,6 @@ gnc_table_traverse_update(Table *table, int row, int col,
|
||||
}
|
||||
}
|
||||
|
||||
if (gnc_register_cell_valid(table, *dest_row, *dest_col, GNC_F))
|
||||
break;
|
||||
|
||||
if (!gnc_table_find_valid_cell_horiz(table, dest_row, dest_col, GNC_F))
|
||||
return GNC_T;
|
||||
|
||||
break;
|
||||
|
||||
case GNC_TABLE_TRAVERSE_UP:
|
||||
|
@ -247,13 +247,15 @@
|
||||
;; Copy a scheme representation of a transaction onto a C transaction.
|
||||
;; guid-mapping must be an alist, mapping guids to guids. This list is
|
||||
;; used to use alternate account guids when creating splits.
|
||||
(define (gnc:transaction-scm-onto-transaction trans-scm trans guid-mapping)
|
||||
(define (gnc:transaction-scm-onto-transaction trans-scm trans guid-mapping
|
||||
commit?)
|
||||
(if (pointer-token-null? trans)
|
||||
#f
|
||||
(begin
|
||||
|
||||
;; open the transaction for editing
|
||||
(gnc:transaction-begin-edit trans 1)
|
||||
(if (not (gnc:transaction-is-open trans))
|
||||
(gnc:transaction-begin-edit trans 1))
|
||||
|
||||
;; copy in the transaction values
|
||||
(let ((description (gnc:transaction-scm-get-description trans-scm))
|
||||
@ -285,4 +287,5 @@
|
||||
(loop (cdr split-scms)))))
|
||||
|
||||
;; close the transaction
|
||||
(gnc:transaction-commit-edit trans))))
|
||||
(if commit?
|
||||
(gnc:transaction-commit-edit trans)))))
|
||||
|
@ -68,13 +68,6 @@
|
||||
(list "Extensions" "")
|
||||
(lambda () (gnc:main-win-export-data-as-text win))))
|
||||
|
||||
(define qif-item
|
||||
(gnc:make-menu-item "QIF File Import (Danger: Unfinished)"
|
||||
"Import QIF File - Scripted in Guile."
|
||||
(list "Extensions"
|
||||
"Export data as text (Danger: Unfinished)")
|
||||
(lambda () (gnc:extensions-qif-import win))))
|
||||
|
||||
(define strings-item
|
||||
(gnc:make-menu-item
|
||||
"Save Translatable Strings"
|
||||
|
@ -382,6 +382,17 @@ the account instead of opening a register." #f))
|
||||
"General" "Use accounting labels"
|
||||
"e" "Only use 'debit' and 'credit' instead of informal synonyms" #f))
|
||||
|
||||
;(gnc:register-configuration-option
|
||||
; (gnc:make-number-range-option
|
||||
; "General" "Default precision"
|
||||
; "f" "Default number of decimal places to display"
|
||||
; 15.0 ;; default
|
||||
; 1.0 ;; lower bound
|
||||
; 200.0 ;; upper bound
|
||||
; 0.0 ;; number of decimals
|
||||
; 1.0 ;; step size
|
||||
; ))
|
||||
|
||||
|
||||
;; Configuation variables
|
||||
|
||||
|
@ -518,7 +518,7 @@
|
||||
'ascend
|
||||
(list
|
||||
#(ascend "Ascending" "smallest to largest, earliest to latest")
|
||||
#(descend "Descending" "largest to t, latest to earliest")))))
|
||||
#(descend "Descending" "largest to smallest, latest to earliest")))))
|
||||
|
||||
(gnc:register-trep-option
|
||||
(gnc:make-simple-boolean-option
|
||||
|
Loading…
Reference in New Issue
Block a user