diff --git a/src/FileDialog.c b/src/FileDialog.c index 3988c15ffa..90b0ecc300 100644 --- a/src/FileDialog.c +++ b/src/FileDialog.c @@ -21,28 +21,26 @@ #include "config.h" -#include #include #include +#include +#include "Destroy.h" #include "FileBox.h" #include "FileDialog.h" #include "FileIO.h" #include "Group.h" -#include "messages.h" -#include "Session.h" #include "TransLog.h" -#include "Destroy.h" +#include "file-history.h" #include "gnc-engine-util.h" #include "gnc-ui.h" -#include "file-history.h" +#include "messages.h" /* This static indicates the debugging module that this .o belongs to. */ static short module = MOD_GUI; /** GLOBALS *********************************************************/ -static Session *current_session = NULL; -static AccountGroup *topgroup = NULL; /* the current top of the hierarchy */ +static GNCBook *current_book = NULL; /* ======================================================== */ @@ -55,7 +53,7 @@ file_not_found_msg (void) /* ======================================================== */ static gboolean -show_file_error (GNCFileIOError io_error, char *newfile) +show_file_error (GNCFileIOError io_error, const char *newfile) { gboolean uh_oh = FALSE; char *buf = NULL; @@ -113,9 +111,9 @@ show_file_error (GNCFileIOError io_error, char *newfile) /* ======================================================== */ static gboolean -show_session_error(Session *session, char *newfile) +show_book_error(GNCBook *book, const char *newfile) { - int norr = xaccSessionGetError (session); + int norr = gnc_book_get_error (book); gboolean uh_oh = FALSE; char *buf = NULL; @@ -147,38 +145,30 @@ show_session_error(Session *session, char *newfile) void gncFileNew (void) { - Session *sess; - AccountGroup *grp; + GNCBook *book; + AccountGroup *group; - /* If user attempts to start a new session before saving - * results of the last one, prompt them to clean up their - * act. */ + /* If user attempts to start a new session before saving results of + * the last one, prompt them to clean up their act. */ if (!gncFileQuerySave ()) return; - sess = current_session; - grp = xaccSessionGetGroup (sess); - /* if session not yet started ... */ - if (!grp) grp = topgroup; + book = gncGetCurrentBook (); + group = gnc_book_get_group (book); /* when starting new everything, destroy old stuff first */ /* destroy open windows first, before destroying the group itself */ - xaccGroupWindowDestroy (grp); - - /* close any ongoing file sessions, if any */ - xaccSessionEnd (sess); - xaccSessionDestroy (sess); - current_session = NULL; - topgroup = NULL; + xaccGroupWindowDestroy (group); - /* disable logging while we move over to the new set of accounts to - * edit; the mass deletion of accounts and transactions during - * switchover is not something we want to keep in a journal. */ + /* close any ongoing file sessions, and free the accounts. + * disable logging so we don't get all that junk. */ xaccLogDisable(); - xaccFreeAccountGroup (grp); + gnc_book_destroy (book); + current_book = NULL; xaccLogEnable(); - grp = xaccMallocAccountGroup(); - topgroup = grp; + + /* start a new book */ + gncGetCurrentBook (); } /* ======================================================== */ @@ -186,16 +176,14 @@ gncFileNew (void) gboolean gncFileQuerySave (void) { - Session *sess; - AccountGroup *grp; + GNCBook *book; + AccountGroup *group; gncUIWidget app; - sess = current_session; - grp = xaccSessionGetGroup (sess); - /* if session not yet started ... */ - if (!grp) grp = topgroup; + book = gncGetCurrentBook (); + group = gnc_book_get_group (book); - app = gnc_get_ui_data(); + app = gnc_get_ui_data (); /* If user wants to mess around before finishing business with * the old file, give em a chance to figure out what's up. @@ -203,7 +191,7 @@ gncFileQuerySave (void) * up the file-selection dialog, we don't blow em out of the water; * instead, give them another chance to say "no" to the verify box. */ - while ( xaccGroupNotSaved (grp) ) + while (xaccGroupNotSaved (group)) { GNCVerifyResult result; const char *message = _("Changes have been made since the last " @@ -252,15 +240,17 @@ gncLockFailHandler (const char *file) static void gncPostFileOpen (const char * filename) { - Session *newsess; - AccountGroup *oldgrp; + GNCBook *new_book; + AccountGroup *old_group; gboolean uh_oh = FALSE; - AccountGroup *newgrp; + AccountGroup *new_group; char * newfile; if (!filename) return; + newfile = xaccResolveFilePath (filename); - if (!newfile) { + if (!newfile) + { char *buf = g_strdup_printf (file_not_found_msg(), filename); gnc_error_dialog (buf); g_free(buf); @@ -269,47 +259,43 @@ gncPostFileOpen (const char * filename) /* -------------- BEGIN CORE SESSION CODE ------------- */ /* -- this code is almost identical in FileOpen and FileSaveAs -- */ - oldgrp = xaccSessionGetGroup (current_session); - /* if session not yet started ... */ - if (!oldgrp) oldgrp = topgroup; + old_group = gnc_book_get_group (gncGetCurrentBook ()); /* load the accounts from the users datafile */ - /* but first, check to make sure we've got a session going ... */ - newsess = xaccMallocSession (); + /* but first, check to make sure we've got a book going. */ + new_book = gnc_book_new (); /* disable logging while we move over to the new set of accounts to * edit; the mass deletetion of accounts and transactions during * switchover is not something we want to keep in a journal. */ - gnc_set_busy_cursor(NULL); - xaccLogDisable(); - newgrp = NULL; - if(xaccSessionBeginFile(newsess, newfile, gncLockFailHandler)) { - if(xaccSessionLoad(newsess)) { - newgrp = xaccSessionGetGroup(newsess); - } + gnc_set_busy_cursor (NULL); + xaccLogDisable (); + new_group = NULL; + if (gnc_book_begin_file (new_book, newfile, gncLockFailHandler)) + { + if (gnc_book_load (new_book)) + new_group = gnc_book_get_group (new_book); } - xaccLogEnable(); - gnc_unset_busy_cursor(NULL); + xaccLogEnable (); + gnc_unset_busy_cursor (NULL); - /* check for session errors, put up appropriate dialog */ - uh_oh = show_session_error (newsess, newfile); + /* check for book errors, put up appropriate dialog */ + uh_oh = show_book_error (new_book, newfile); if (!uh_oh) { - GNCFileIOError io_err = xaccSessionGetFileError(newsess); + GNCFileIOError io_err = gnc_book_get_file_error (new_book); + /* check for i/o error, put up appropriate error message */ uh_oh = show_file_error(io_err, newfile); if (uh_oh) - { - xaccFreeAccountGroup (newgrp); - newgrp = NULL; - } + new_group = NULL; /* Umm, came up empty-handed, i.e. the file was not found. */ /* This is almost certainly not what the user wanted. */ - if (!uh_oh && !newgrp && (io_err == ERR_FILEIO_NONE)) + if (!uh_oh && !new_group && (io_err == ERR_FILEIO_NONE)) { - char *buf = g_strdup_printf (file_not_found_msg(), newfile); + char *buf = g_strdup_printf (file_not_found_msg(), newfile); gnc_error_dialog (buf); g_free (buf); uh_oh = TRUE; @@ -319,50 +305,46 @@ gncPostFileOpen (const char * filename) /* going down -- abandon ship */ if (uh_oh) { - xaccSessionEnd (newsess); - xaccSessionDestroy (newsess); - - /* well, no matter what, I think its a good idea to have - * a topgroup around. For example, early in the gnucash startup - * sequence, the user opens a file; if this open fails for any - * reason, we don't want to leave them high & dry without a topgroup, - * because if the user continues, then bad things will happen. - */ - if (NULL == topgroup) - { - topgroup = xaccMallocAccountGroup(); - } + gnc_book_destroy (new_book); + + /* well, no matter what, I think its a good idea to have a + * topgroup around. For example, early in the gnucash startup + * sequence, the user opens a file; if this open fails for any + * reason, we don't want to leave them high & dry without a + * topgroup, because if the user continues, then bad things will + * happen. */ + gncGetCurrentBook (); + free (newfile); return; } /* if we got to here, then we've successfully gotten a new session */ /* close up the old file session (if any) */ - xaccSessionEnd (current_session); - xaccSessionDestroy (current_session); - current_session = newsess; - /* --------------- END CORE SESSION CODE -------------- */ - - /* clean up old stuff, and then we're outta here. */ xaccLogDisable(); xaccLogSetBaseName (newfile); - gnc_history_add_file (newfile); - /* destroy open windows first, before destroying the group itself */ - xaccGroupWindowDestroy (oldgrp); - xaccFreeAccountGroup (oldgrp); - topgroup = newgrp; + + xaccGroupWindowDestroy (old_group); + gnc_book_destroy (current_book); + current_book = new_book; + xaccLogEnable(); + /* --------------- END CORE SESSION CODE -------------- */ + + /* clean up old stuff, and then we're outta here. */ + gnc_history_add_file (newfile); free (newfile); - /* run a file-opened hook. For now, the main thing it will do + /* run a file-opened hook. For now, the main thing it will do * is notice if legacy currencies are being imported. */ { SCM run_danglers = gh_eval_str("gnc:hook-run-danglers"); SCM hook = gh_eval_str("gnc:*file-opened-hook*"); SCM filename; - - if(newfile) { + + if (newfile) + { filename = gh_str02scm(newfile); gh_call2(run_danglers, hook, filename); } @@ -386,8 +368,7 @@ gncFileOpen (void) * user fails to pick a file (by e.g. hitting the cancel button), we * might be left with a null topgroup, which leads to nastiness when * user goes to create their very first account. So create one. */ - if (topgroup == NULL) - topgroup = xaccMallocAccountGroup(); + gncGetCurrentBook (); } void @@ -402,22 +383,23 @@ gncFileOpenFile (const char * newfile) } /* ======================================================== */ -static int been_here_before = 0; +static gboolean been_here_before = FALSE; void gncFileSave (void) { - AccountGroup *newgrp = NULL; - char * newfile; GNCFileIOError io_err; - int norr, uh_oh = 0; + const char * newfile; + GNCBook *book; + int uh_oh = 0; + int norr; /* hack alert -- Somehow make sure all in-progress edits get committed! */ - /* if no session exists, then we don't have a filename/path - * to save to. Get one now. */ - if ((NULL == current_session) || - (NULL == xaccSessionGetGroup (current_session))) + /* If we don't have a filename/path to save to get one. */ + book = gncGetCurrentBook (); + + if (!gnc_book_get_file_path (book)) { gncFileSaveAs(); return; @@ -425,19 +407,19 @@ gncFileSave (void) /* use the current session to save to file */ gnc_set_busy_cursor(NULL); - xaccSessionSave (current_session); + gnc_book_save (book); gnc_unset_busy_cursor(NULL); /* Make sure everything's OK - disk could be full, file could have become read-only etc. */ - norr = xaccSessionGetError (current_session); + norr = gnc_book_get_error (book); if (norr) { const char *format = _("There was an error writing the file\n %s" "\n\n%s"); char *message; - newfile = xaccSessionGetFilePath(current_session); + newfile = gnc_book_get_file_path (book); if (newfile == NULL) newfile = ""; @@ -447,9 +429,9 @@ gncFileSave (void) if (been_here_before) return; - been_here_before = 1; + been_here_before = TRUE; gncFileSaveAs(); /* been_here prevents infinite recuirsion */ - been_here_before = 0; + been_here_before = FALSE; return; } @@ -457,21 +439,16 @@ gncFileSave (void) /* check for i/o error, put up appropriate error message. * NOTE: the file-writing routines never set the file io * error code, so this seems to be unneccesary. */ - io_err = xaccSessionGetFileError(current_session); - newfile = xaccSessionGetFilePath(current_session); - gnc_history_add_file(newfile); + io_err = gnc_book_get_file_error (book); + newfile = gnc_book_get_file_path (book); + gnc_history_add_file (newfile); uh_oh = show_file_error (io_err, newfile); - if (uh_oh) - { - xaccFreeAccountGroup (newgrp); - newgrp = NULL; - } /* going down -- abandon ship */ if (uh_oh) return; - xaccGroupMarkSaved (topgroup); + xaccGroupMarkSaved (gnc_book_get_group (book)); } /* ======================================================== */ @@ -479,81 +456,80 @@ gncFileSave (void) void gncFileSaveAs (void) { - Session *newsess; - AccountGroup *oldgrp; + AccountGroup *group; + GNCBook *new_book; + GNCBook *book; const char *filename; char *newfile; - char * oldfile; + const char *oldfile; gboolean uh_oh = FALSE; filename = fileBox(_("Save"), "*.gnc"); if (!filename) return; - /* check to see if the user did something silly, - * like specifying the same file as the current file ... - * if so, then just do that, instead of the below, - * which assumes a truly new name was given. - */ + /* Check to see if the user specified the same file as the current + * file. If so, then just do that, instead of the below, which + * assumes a truly new name was given. */ newfile = xaccResolveFilePath (filename); - if (!newfile) { + if (!newfile) + { char *buf = g_strdup_printf (file_not_found_msg(), filename); gnc_error_dialog (buf); g_free (buf); return; } - oldfile = xaccSessionGetFilePath (current_session); - if (oldfile && (strcmp(oldfile, newfile) == 0)) { + + book = gncGetCurrentBook (); + oldfile = gnc_book_get_file_path (book); + if (oldfile && (strcmp(oldfile, newfile) == 0)) + { free (newfile); gncFileSave (); return; } /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */ - oldgrp = xaccSessionGetGroup (current_session); - /* if session not yet started ... */ - if (!oldgrp) oldgrp = topgroup; - - /* create a new session ... */ - newsess = xaccMallocSession (); + group = gnc_book_get_group (book); /* disable logging while we move over to the new set of accounts to * edit; the mass deletetion of accounts and transactions during - * switchover is not something we want to keep in a journal. */ - xaccLogDisable(); - xaccSessionBeginFile(newsess, newfile, gncLockFailHandler); - xaccLogEnable(); + * switchover is not something we want to keep in a journal. */ + xaccLogDisable (); + new_book = gnc_book_new (); + gnc_book_begin_file (new_book, newfile, gncLockFailHandler); + xaccLogEnable (); /* check for session errors (e.g. file locked by another user) */ - uh_oh = show_session_error (newsess, newfile); + uh_oh = show_book_error (new_book, newfile); /* No check for file errors since we didn't read a file... */ /* going down -- abandon ship */ - if (uh_oh) { - xaccSessionDestroy (newsess); - - /* well, no matter what, I think its a good idea to have - * a topgroup around. For example, early in the gnucash startup - * sequence, the user opens a file ... if this open fails for any - * reason, we don't want to leave them high & dry without a topgroup, - * because if user continues, then bad things will happen ... - */ - if(NULL == topgroup) { - topgroup = xaccMallocAccountGroup(); - } + if (uh_oh) + { + xaccLogDisable (); + gnc_book_destroy (new_book); + xaccLogEnable (); + free (newfile); gnc_refresh_main_window(); + return; } /* if we got to here, then we've successfully gotten a new session */ /* close up the old file session (if any) */ - xaccSessionDestroy (current_session); - current_session = newsess; + xaccLogDisable (); + gnc_book_set_group (book, NULL); + gnc_book_destroy (book); + current_book = new_book; + xaccLogEnable (); + /* --------------- END CORE SESSION CODE -------------- */ /* oops ... file already exists ... ask user what to do... */ - if(xaccSessionSaveMayClobberData(newsess)) { + if (gnc_book_save_may_clobber_data (new_book)) + { const char *format = _("The file \n %s\n already exists.\n" "Are you sure you want to overwrite it?"); char *tmpmsg; @@ -567,20 +543,17 @@ gncFileSaveAs (void) if (!result) return; - /* Whoa-ok. Blow away the previous file. - * Do not disable logging ... we want to capture the - * old file in the log, just in case the user later - * decides it was all a big mistake. */ - xaccSessionSetGroup (newsess, NULL); - /* xaccLogDisable(); no don't disable, keep logging on */ + /* Whoa-ok. Blow away the previous file. Do not disable + * logging. We want to capture the old file in the log, just in + * case the user later decides it was all a big mistake. */ } /* OK, save the data to the file ... */ xaccLogSetBaseName (newfile); - xaccSessionSetGroup (newsess, oldgrp); + gnc_book_set_group (new_book, group); gncFileSave (); - free (newfile); + free (newfile); gnc_refresh_main_window(); } @@ -589,21 +562,16 @@ gncFileSaveAs (void) void gncFileQuit (void) { - AccountGroup *grp; + GNCBook *book; - grp = xaccSessionGetGroup (current_session); - /* if session not yet started ... */ - if (!grp) grp = topgroup; + book = gncGetCurrentBook (); /* disable logging; the mass deletetion of accounts and transactions * during shutdown is not something we want to keep in a journal. */ xaccLogDisable(); - xaccSessionEnd (current_session); - xaccSessionDestroy (current_session); - current_session = NULL; - xaccFreeAccountGroup (grp); - topgroup = NULL; + gnc_book_destroy (book); + current_book = NULL; } /* ======================================================== */ @@ -611,27 +579,22 @@ gncFileQuit (void) AccountGroup * gncGetCurrentGroup (void) { - AccountGroup *grp; - grp = xaccSessionGetGroup (current_session); - if (grp) return grp; - - /* If we are here, then no session has yet been started ... */ - grp = topgroup; - if (grp) return grp; + GNCBook *book; - /* if we are here, then topgroup not yet initialized ... */ - xaccLogEnable(); - topgroup = xaccMallocAccountGroup(); + book = gncGetCurrentBook (); - return topgroup; + return gnc_book_get_group (book); } /* ======================================================== */ -Session * -gncGetCurrentSession (void) +GNCBook * +gncGetCurrentBook (void) { - return (current_session); + if (!current_book) + current_book = gnc_book_new (); + + return current_book; } /********************* END OF FILE **********************************/ diff --git a/src/FileDialog.h b/src/FileDialog.h index 4d2dd8b32d..b7870ff15e 100644 --- a/src/FileDialog.h +++ b/src/FileDialog.h @@ -122,7 +122,7 @@ #include "config.h" #include "Group.h" -#include "Session.h" +#include "gnc-book.h" void gncFileNew (void); void gncFileOpen (void); @@ -138,6 +138,6 @@ void gncFileQuit (void); AccountGroup *gncGetCurrentGroup (void); -Session *gncGetCurrentSession (void); +GNCBook *gncGetCurrentBook (void); #endif /* __GNC_FILE_DIALOG_H__ */ diff --git a/src/engine/BackendP.h b/src/engine/BackendP.h index 388579f0a0..67498e388c 100644 --- a/src/engine/BackendP.h +++ b/src/engine/BackendP.h @@ -5,7 +5,7 @@ * back-ends (which will probably be sql databases). * * The callbacks will be called at the appropriate times during - * a session to allow the backend to store the data as needed. + * a book session to allow the backend to store the data as needed. * */ @@ -13,10 +13,11 @@ #define __XACC_BACKEND_P_H__ #include "config.h" + #include "Account.h" #include "Group.h" -#include "Session.h" #include "Transaction.h" +#include "gnc-book.h" typedef struct _backend Backend; @@ -31,8 +32,8 @@ typedef struct _backend Backend; struct _backend { - AccountGroup * (*session_begin) (Session *, const char * sessionid); - int (*session_end) (Session *); + AccountGroup * (*book_begin) (GNCBook *, const char * book_id); + int (*book_end) (GNCBook *); int (*account_begin_edit) (Backend *, Account *, int defer); int (*account_commit_edit) (Backend *, Account *); int (*trans_begin_edit) (Backend *, Transaction *, int defer); @@ -60,7 +61,7 @@ Backend * xaccTransactionGetBackend (Transaction *); */ void xaccGroupSetBackend (AccountGroup *, Backend *); Backend * xaccGroupGetBackend (AccountGroup *); -Backend * xaccSessionGetBackend (Session *); +Backend * xaccGNCBookGetBackend (GNCBook *book); #endif /* __XACC_BACKEND_P_H__ */ diff --git a/src/engine/Group.c b/src/engine/Group.c index 06af9e5370..fcf10033e9 100644 --- a/src/engine/Group.c +++ b/src/engine/Group.c @@ -144,8 +144,8 @@ xaccFreeAccountGroup( AccountGroup *grp ) xaccAccountGroupBeginEdit (grp, 1); - for( i=0; inumAcc; i++ ) - xaccFreeAccount( grp->account[i] ); + for(i = 0; i < grp->numAcc; i++ ) + xaccFreeAccount(grp->account[i]); g_free(grp->account); diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 3872528ca6..ac17177c2d 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -14,7 +14,6 @@ libgncengine_la_SOURCES = \ Group.c \ Query.c \ Scrub.c \ - Session.c \ Transaction.c \ TransLog.c \ date.c \ @@ -25,7 +24,8 @@ libgncengine_la_SOURCES = \ io-gncxml-w.c \ md5.c \ kvp_frame.c \ - gnc-commodity.c\ + gnc-book.c \ + gnc-commodity.c \ gnc-numeric.c \ gnc-engine.c \ gnc-engine-util.c @@ -45,7 +45,6 @@ noinst_HEADERS = \ GroupP.h \ Query.h \ Scrub.h \ - Session.h \ TransLog.h \ Transaction.h \ TransactionP.h \ @@ -56,6 +55,7 @@ noinst_HEADERS = \ io-gncxml.h \ md5.h \ kvp_frame.h \ + gnc-book.h \ gnc-commodity.h \ gnc-numeric.h \ gnc-engine.h \ diff --git a/src/engine/Session.c b/src/engine/Session.c deleted file mode 100644 index 32216a6a1c..0000000000 --- a/src/engine/Session.c +++ /dev/null @@ -1,639 +0,0 @@ -/********************************************************************\ - * 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 * -\********************************************************************/ - -/* - * FILE: - * Session.c - * - * FUNCTION: - * Provide wrappers for initiating/concluding a file-editing session. - * - * HISTORY: - * Created by Linas Vepstas December 1998 - * Copyright (c) 1998-2000 Linas Vepstas - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "BackendP.h" -#include "FileIO.h" -#include "Group.h" -#include "Session.h" -#include "gnc-engine-util.h" - - -struct _session { - AccountGroup *topgroup; - - /* the requested session id, in the form or a URI, such as - * file:/some/where, or sql:server.host.com:555 - */ - char *sessionid; - - /* if session failed, this records the failure reason - * (file not found, etc). - * the standard errno values are used. - */ - int errtype; - - /* FIXME: This is a hack. I'm trying to move us away from static - global vars. This may be a temp fix if we decide to integrate - FileIO errors into Session errors... */ - GNCFileIOError last_file_err; - - /* ---------------------------------------------------- */ - /* teh following struct members apply only for file-io */ - /* the fully-resolved path to the file */ - char *fullpath; - - /* name of lockfile, and filedescr */ - char * lockfile; - char * linkfile; - int lockfd; - - /* ---------------------------------------------------- */ - /* this struct member applies only for SQL i/o */ - Backend *backend; - -}; - -/* ============================================================== */ - -Session * -xaccMallocSession (void) -{ - Session *sess; - sess = g_new(Session, 1); - - xaccInitSession (sess); - return sess; -} - -void -xaccInitSession (Session *sess) -{ - if (!sess) return; - sess->topgroup = NULL; - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - sess->sessionid = NULL; - sess->fullpath = NULL; - sess->lockfile = NULL; - sess->linkfile = NULL; - sess->lockfd = -1; - sess->backend = NULL; -}; - -/* ============================================================== */ - -int -xaccSessionGetError (Session * sess) -{ - int retval; - - if (!sess) return EINVAL; - retval = sess->errtype; - sess->errtype = 0; - return (retval); -} - -/* ============================================================== */ - -GNCFileIOError -xaccSessionGetFileError (Session * sess) { - if (!sess) return ERR_FILEIO_MISC; - return sess->last_file_err; -} - -/* ============================================================== */ - -AccountGroup * -xaccSessionGetGroup (Session *sess) -{ - if (!sess) return NULL; - return (sess->topgroup); -} - -void -xaccSessionSetGroup (Session *sess, AccountGroup *grp) -{ - if (!sess) return; - sess->topgroup = grp; -} - -/* ============================================================== */ - -Backend * -xaccSessionGetBackend (Session *sess) -{ - if (!sess) return NULL; - return (sess->backend); -} - -/* ============================================================== */ - -char * -xaccSessionGetFilePath (Session *sess) -{ - if (!sess) return NULL; - return (sess->fullpath); -} - -/* ============================================================== */ - -gboolean -xaccSessionBegin (Session *sess, const char * sid) { - - if(!sess) return FALSE; - if(!sid) return FALSE; - - /* clear the error condition of previous errors */ - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - - /* check to see if this session is already open */ - if (sess->sessionid) { - sess->errtype = ETXTBSY; - return FALSE; - } - - /* seriously invalid */ - if (!sid) { - sess->errtype = EINVAL; - return FALSE; - } - - /* check to see if this is a type we know how to handle */ - if(strncmp(sid, "file:", 5) != 0) { - sess->errtype = ENOSYS; - return FALSE; - } - - /* add 5 to space past 'file:' */ - return xaccSessionBeginFile(sess, sid+5, NULL); -} - -/* ============================================================== */ - -#if 0 -static AccountGroup * -xaccSessionBeginSQL (Session *sess, const char * dbname) -{ - Backend *be = NULL; - AccountGroup *grp = NULL; - - if (!sess) return NULL; - -/* #define SQLHACK */ -#ifdef SQLHACK - { - /* for testing the sql, just a hack, remove later ... */ -extern Backend * pgendNew (void); - be = pgendNew (); - } -#endif - - sess->backend = be; - - if (be && be->session_begin) { - grp = (be->session_begin) (sess, dbname); - } - /* comment out until testing done, else clobber file ...*/ - /* sess->topgroup = grp; */ - xaccGroupSetBackend (sess->topgroup, be); - - return (sess->topgroup); -} -#endif - -/* ============================================================== */ - -static gboolean -xaccSessionGetFileLock (Session *sess) -{ - struct stat statbuf; - char pathbuf[PATH_MAX]; - char *path = NULL; - int rc; - - rc = stat (sess->lockfile, &statbuf); - if (!rc) { - /* oops .. file is all locked up .. */ - sess->errtype = ETXTBSY; - return FALSE; - } - - sess->lockfd = open (sess->lockfile, O_RDWR | O_CREAT | O_EXCL , 0); - if (0 > sess->lockfd) { - /* oops .. file is all locked up .. */ - sess->errtype = ETXTBSY; - return FALSE; - } - - /* OK, now work around some NFS atomic lock race condition - * mumbo-jumbo. We do this by linking a unique file, and - * then examing the link count. At least that's what the - * NFS programmers guide suggests. - * Note: the "unique filename" must be unique for the - * triplet filename-host-process, otherwise accidental - * aliases can occur. - */ - - /* apparently, even this code may not work for some NFS - * implementations. In the long run, I am told that - * ftp.debian.org - * /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz - * provides a better long-term solution. - */ - - strcpy (pathbuf, sess->lockfile); - path = strrchr (pathbuf, '.'); - sprintf (path, ".%lx.%d.LNK", gethostid(), getpid()); - link (sess->lockfile, pathbuf); - rc = stat (sess->lockfile, &statbuf); - if (rc) { - /* oops .. stat failed! This can't happen! */ - sess->errtype = ETXTBSY; - unlink (pathbuf); - close (sess->lockfd); - unlink (sess->lockfile); - return FALSE; - } - - if (2 != statbuf.st_nlink) { - /* oops .. stat failed! This can't happen! */ - sess->errtype = ETXTBSY; - unlink (pathbuf); - close (sess->lockfd); - unlink (sess->lockfile); - return FALSE; - } - - sess->linkfile = g_strdup (pathbuf); - - return TRUE; -} - -/* ============================================================== */ - -gboolean -xaccSessionBeginFile (Session *sess, const char * filefrag, - SessionLockFailHandler handler) { - - if(!sess) return FALSE; - if(!filefrag) return FALSE; - - /* clear the error condition of previous errors */ - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - - /* check to see if this session is already open */ - if (sess->sessionid) { - sess->errtype = ETXTBSY; - return FALSE; - } - - /* seriously invalid */ - if (!filefrag) { - sess->errtype = EINVAL; - return FALSE; - } - - /* ---------------------------------------------------- */ - /* OK, now we try to find or build an absolute file path */ - - sess->fullpath = xaccResolveFilePath (filefrag); - if (! (sess->fullpath)) { - sess->errtype = ERANGE; - return FALSE; /* ouch */ - } - - /* Store the sessionid URL also ... */ - sess->sessionid = g_strconcat ("file:", filefrag, NULL); - - /* ---------------------------------------------------- */ - /* We should now have a fully resolved path name. - * Lets see if we can get a lock on it. */ - - sess->lockfile = g_strconcat(sess->fullpath, ".LCK", NULL); - - if (!xaccSessionGetFileLock (sess)) { - if (!handler || !handler (sess->fullpath)) { - g_free (sess->sessionid); sess->sessionid = NULL; - g_free (sess->fullpath); sess->fullpath = NULL; - g_free (sess->lockfile); sess->lockfile = NULL; - return FALSE; - } - } - - return TRUE; -} - -#ifdef SQLHACK - /* for testing the sql, just a hack, remove later ... */ - /* this should never ever appear here ... */ - xaccSessionBeginSQL (sess, "postgres://localhost/gnc_bogus"); -#endif - -/* ============================================================== */ - -gboolean -xaccSessionLoad(Session *sess) { - if(!sess) return FALSE; - if(!sess->sessionid) return FALSE; - - if(strncmp(sess->sessionid, "file:", 5) == 0) { - /* file: */ - - if(!sess->lockfile) { - sess->errtype = ENOLCK; - return FALSE; - } - - /* At this point, we should have a valid session id and a lock on - the file. */ - - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - sess->topgroup = xaccReadAccountGroupFile (sess->fullpath, - &(sess->last_file_err)); - - if(!sess->topgroup || (sess->last_file_err != ERR_FILEIO_NONE)) { - sess->errtype = EIO; - return FALSE; - } - - return TRUE; - - } else { - sess->errtype = ENOSYS; - return FALSE; - } -} - -/* ============================================================== */ - -gboolean -xaccSessionSaveMayClobberData(Session *s) { - /* FIXME: Make sure this doesn't need more sophisticated semantics - in the face of special file, devices, pipes, symlinks, etc... */ - - struct stat statbuf; - - if(!s) return FALSE; - if(!s->fullpath) return FALSE; - if(stat(s->fullpath, &statbuf) == 0) return TRUE; - return FALSE; - -#ifdef SQLHACK - /* for testing the sql, just a hack, remove later ... */ - /* this should never ever appear here ... */ - xaccSessionBeginSQL (sess, "postgres://localhost/gnc_bogus"); -#endif - -} - -/* ============================================================== */ - -void -xaccSessionSave (Session *sess) -{ - if (!sess) return; - - /* if the fullpath doesn't exist, either the user failed to initialize, - * or the lockfile was never obtained ... either way, we can't write. */ - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - - if (!(sess->fullpath)) { - sess->errtype = ENOLCK; - return; - } - - if (sess->topgroup) { - gboolean write_ok = xaccWriteAccountGroupFile (sess->fullpath, - sess->topgroup, - TRUE, - &(sess->last_file_err)); - if (!write_ok) sess->errtype = errno; - } -} - -/* ============================================================== */ - -void -xaccSessionEnd (Session *sess) -{ - if (!sess) return; - sess->errtype = 0; - sess->last_file_err = ERR_FILEIO_NONE; - - if (sess->linkfile) unlink (sess->linkfile); - if (0 < sess->lockfd) close (sess->lockfd); - if (sess->lockfile) unlink (sess->lockfile); - - g_free (sess->sessionid); - sess->sessionid = NULL; - - g_free (sess->fullpath); - sess->fullpath = NULL; - - g_free (sess->lockfile); - sess->lockfile = NULL; - - g_free (sess->linkfile); - sess->linkfile = NULL; - - sess->topgroup = NULL; -} - -void -xaccSessionDestroy (Session *sess) -{ - if (!sess) return; - xaccSessionEnd (sess); - g_free (sess); -} - - -/* ============================================================== */ -/* - * If $HOME/.gnucash/data directory doesn't exist, then create it. - */ - -static void -MakeHomeDir (void) -{ - int rc; - struct stat statbuf; - char *home; - char *path; - char *data; - - /* Punt. Can't figure out where home is. */ - home = getenv ("HOME"); - if (!home) return; - - path = g_strconcat(home, "/.gnucash", NULL); - - rc = stat (path, &statbuf); - if (rc) { - /* assume that the stat failed only because the dir is absent, - * and not because its read-protected or other error. - * Go ahead and make it. Don't bother much with checking mkdir - * for errors; seems pointless. */ - mkdir (path, S_IRWXU); /* perms = S_IRWXU = 0700 */ - } - - data = g_strconcat (path, "/data", NULL); - rc = stat (data, &statbuf); - if (rc) - mkdir (data, S_IRWXU); - - g_free (path); - g_free (data); -} - -/* ============================================================== */ - -/* XXX hack alert -- we should be yanking this out of - * some config file - */ -static char * searchpaths[] = { - "/usr/share/gnucash/data/", - NULL, -}; - -char * -xaccResolveFilePath (const char * filefrag) -{ - struct stat statbuf; - char pathbuf[PATH_MAX]; - char *path = NULL; - int namelen, len; - int i, rc; - - /* seriously invalid */ - if (!filefrag) return NULL; - - /* ---------------------------------------------------- */ - /* OK, now we try to find or build an absolute file path */ - - /* check for an absolute file path */ - if ('/' == *filefrag) - return strdup (filefrag); - - /* get conservative on the length so that sprintf(getpid()) works ... */ - /* strlen ("/.LCK") + sprintf (%x%d) */ - namelen = strlen (filefrag) + 25; - - for (i=-2; 1 ; i++) - { - - switch (i) { - case -2: { - /* try to find a file by this name in the cwd ... */ - path = getcwd (pathbuf, PATH_MAX); - if (!path) continue; - len = strlen (path) + namelen; - if (PATH_MAX <= len) continue; - strcat (path, "/"); - break; - } - case -1: { - /* look for something in $HOME/.gnucash/data */ - path = getenv ("HOME"); - if (!path) continue; - len = strlen (path) + namelen + 20; - if (PATH_MAX <= len) continue; - strcpy (pathbuf, path); - strcat (pathbuf, "/.gnucash/data/"); - path = pathbuf; - break; - } - default: { - /* OK, check the user-configured paths */ - path = searchpaths[i]; - if (path) { - len = strlen (path) + namelen; - if (PATH_MAX <= len) continue; - strcpy (pathbuf, path); - path = pathbuf; - } - } - } - if (!path) break; - - /* lets see if we found the file here ... */ - /* haral: if !S_ISREG: there is something with that name - * but it's not a regular file */ - strcat (path, filefrag); - rc = stat (path, &statbuf); - if ((!rc) && (S_ISREG(statbuf.st_mode))) { - return (strdup (path)); - } - } - - /* make sure that the gnucash home dir exists. */ - MakeHomeDir(); - - /* OK, we didn't find the file. */ - /* If the user specified a simple filename (i.e. no slashes in it) - * then create the file. But if it has slashes in it, then creating - * a bunch of directories seems like a bad idea; more likely, the user - * specified a bad filename. So return with error. */ - if (strchr (filefrag, '/')) { - return NULL; - } - - /* Lets try creating a new file in $HOME/.gnucash/data */ - path = getenv ("HOME"); - if (path) { - len = strlen (path) + namelen + 50; - if (PATH_MAX > len) { - strcpy (pathbuf, path); - strcat (pathbuf, "/.gnucash/data/"); - strcat (pathbuf, filefrag); - return (strdup (pathbuf)); - } - } - - /* OK, we still didn't find the file */ - /* Lets try creating a new file in the cwd */ - path = getcwd (pathbuf, PATH_MAX); - if (path) { - len = strlen (path) + namelen; - if (PATH_MAX > len) { - strcat (path, "/"); - strcat (path, filefrag); - return (strdup (path)); - } - } - - return NULL; -} - -/* ==================== END OF FILE ================== */ diff --git a/src/engine/Session.h b/src/engine/Session.h deleted file mode 100644 index a3b6c1dbca..0000000000 --- a/src/engine/Session.h +++ /dev/null @@ -1,205 +0,0 @@ -/********************************************************************\ - * 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 * - * * -\********************************************************************/ - -/* - * FILE: - * Session.h - * - * FUNCTION: - * Provide wrappers for initiating/concluding a file-editing session. - * This class provides several important services: - * - * 1) Prevents multiple users from editing the same file at the same - * time, thus avoiding lost data due to race conditions. Thus - * an open session implies that the associated file is locked. - * - * 2) Provides a search path for the file to be edited. This should - * simplify install & maintenance problems for naive users who - * may not have a good grasp on what a file ssytem is, or where - * they want to keep their data files. - * - * The current implementations assumes the use of files and file - * locks; however, the API was designed to be general enough to - * allow the use of generic URL's, and/or implementation on top - * of SQL or other database/persistant object technology. - * - * HISTORY: - * Created by Linas Vepstas December 1998 - * Copyright (c) 1998, 1999 Linas Vepstas - */ - -#ifndef __XACC_SESSION_H__ -#define __XACC_SESSION_H__ - -#include "Group.h" -#include "FileIO.h" - -/** STRUCTS *********************************************************/ -typedef struct _session Session; - -/** PROTOTYPES ******************************************************/ -/* - * The xaccMallocSession() routine simply mallocs memory for a session object. - * The xaccInitSession() routine initializes memory for a session object. - * The xaccSessionDestroy() routine frees the associated memory. - * Note that this routine does *not* free the account group! - */ -Session * xaccMallocSession (void); -void xaccInitSession (Session *); -void xaccSessionDestroy (Session *); - -/* - * The xaccSessionBegin() method begins a new session. It takes as an argument - * the sessionid. The session id must be a string in the form of a URI/URL. - * In the current implementation, only one type of URI is supported, and - * that is the file URI: anything of the form - * "file:/home/somewhere/somedir/file.xac" - * The path part must be a valid path. The file-part must be a valid - * xacc/gnucash-format file. Paths may be relativ or absolute. If the - * path is relative; that is, if the argument is - * "file:somefile.xac" - * then a sequence of search paths are checked for a file of this name. - * - * If the file exists, can be opened and read, then the AccountGroup - * will be returned. Otherwise, NULL is returned, and the reason for - * the NULL can be gotten with xaccSessionGetError(). Note that NULL - * does not always indicate an error ... e.g. if a new file is created, - * NULL is returned, and xaccSessionGetError returns 0. That's OK. - * - * If the file is succesfully opened and read, then a lock will have been - * obtained, and all other access to the file will be denied. This feature - * is intended to be a brute-force global lock to avoid multiple writers. - * - * The xaccSessionBeginFile() routine is identical to the xaccSessionBegin() - * routine, except that the argument is a filename (i.e. the five - * letters "file:" should not be prepended) and there is an additional - * function argument. This function is called if xaccSessionBeginFile - * fails to obtain a lock for the file. If it returns true, the file - * is loaded anyway. If it returns false, or the handler is NULL, a - * failed lock attempt will abort the load. The lock fail handler is - * passed the filename of the data file being loaded. - * - * The xaccSessionGetFilePath() routine returns the fully-qualified file - * path for the session. That is, if a relative or partial filename - * was for the session, then it had to have been fully resolved to - * open the session. This routine returns the result of this resolution. - * - * The xaccSessionGetError() routine can be used to obtain the reason for - * any failure. Standard errno values are used. Calling this routine resets - * the error value. This routine allows an implementation of multiple - * error values, e.g. in a stack, where this routine pops the top value. - * The current implementation has a stack that is one-deep. - * - * Some important error values: - * EINVAL -- bad argument - * ETXTBSY -- session id is in use; its locked by someone else. - * ENOSYS -- unsupported URI type. - * ERANGE -- file path too long - * ENOLCK -- session not open when SessionSave() was called. - * - * - * The xaccSessionGetGroup() method will return the current top-level - * account group. - * - * The xaccSessionSetGroup() method will set the topgroup to a new value. - * - * The xaccSessionSave() method will commit all changes that have been - * made to the top-level account group. In the current - * implementation, this is nothing more than a write to the file of - * the current AccountGroup of the session. - * - * The xaccSessionEnd() method will release the session lock. It will *not* - * save the account group to a file. Thus, this method acts as an "abort" - * or "rollback" primitive. - * - * The xaccResolveFilePath() routine is a utility that will accept a - * fragmentary filename as input, and resolve it into a fully-qualified path - * in the file system, i.e. a path that begins with a leading slash. - * First, the current working directory is searched for the file. - * Next, the directory $HOME/.gnucash/data, and finally, a list of other - * (configurable) paths. If the file is not found, then the path - * $HOME/.gnucash/data is used. If $HOME is not defined, then the current - * working directory is used. - * - * EXAMPLE USAGE: - * To read, modify and save an existing file: - * ------------------------------------------ - * Session *sess = xaccMallocSession (); - * xaccSessionBegin (sess, "file:/some/file.xac"); - * AccountGroup *grp = xaccSessionGetGroup (sess); - * if (grp) { - * ... edit the session ... - * xaccSessionSave (sess); - * } else { - * int err = xaccSessionGetError (sess); - * printf ("%s\n", strerror (err)); - * } - * xaccSessionEnd (sess); - * xaccSessionDestroy (sess); - * - * To save an existing session to a file: - * -------------------------------------- - * AccountGroup * grp = ... - * ... edit accounts, transactions, etc ... - * Session *sess = xaccMallocSession (); - * xaccSessionBegin (sess, "file:/some/file.xac"); - * xaccSessionSetGroup (sess, grp); - * int err = xaccSessionGetError (sess); - * if (0 == err) { - * xaccSessionSave (sess); - * } else { - * printf ("%s\n", strerror (err)); - * } - * xaccSessionEnd (sess); - * xaccSessionDestroy (sess); - * */ - -typedef gboolean (*SessionLockFailHandler)(const char *file); - -/* These do not load anything. */ -gboolean xaccSessionBegin(Session *, const char * sessionid); -gboolean xaccSessionBeginFile(Session *, const char * filename, - SessionLockFailHandler handler); - -/* Loads the account group indicated by SessionBegin. */ -gboolean xaccSessionLoad(Session *); - -int xaccSessionGetError (Session *); - -/* FIXME: This is a hack. I'm trying to move us away from static - global vars. This may be a temp fix if we decide to integrate - FileIO errors into Session errors... This just returns the last - FileIO error, but it doesn't clear it. */ -GNCFileIOError xaccSessionGetFileError (Session *); - -AccountGroup * xaccSessionGetGroup (Session *); -void xaccSessionSetGroup (Session *, AccountGroup *topgroup); -char * xaccSessionGetFilePath (Session *); - -/* FIXME: This isn't as thorough as we might want it to be... */ -gboolean xaccSessionSaveMayClobberData(Session *s); - -void xaccSessionSave (Session *); -void xaccSessionEnd (Session *); - -char * xaccResolveFilePath (const char * filefrag); - -#endif /* __XACC_SESSION_H__ */ -/* ==================== END OF FILE ================== */ diff --git a/src/file-history.h b/src/file-history.h index d8e11464fb..0251d0da48 100644 --- a/src/file-history.h +++ b/src/file-history.h @@ -25,8 +25,8 @@ #define MAX_HISTORY 4 -void gnc_history_add_file(char *); -void gnc_history_update_menu(void); -const char * gnc_history_get_last(void); +void gnc_history_add_file (const char *filename); +void gnc_history_update_menu (void); +const char * gnc_history_get_last (void); #endif diff --git a/src/gnome/file-history.c b/src/gnome/file-history.c index f1d8ff4eee..56568cf818 100644 --- a/src/gnome/file-history.c +++ b/src/gnome/file-history.c @@ -99,7 +99,7 @@ __gnc_history_file_cb(GtkWidget *w, char *data) } void -gnc_history_add_file(char *newfile) +gnc_history_add_file(const char *newfile) { int i, max_files; gboolean used_default, matched = FALSE; diff --git a/src/gnome/window-main.c b/src/gnome/window-main.c index c59ec1f7a5..7c60990419 100644 --- a/src/gnome/window-main.c +++ b/src/gnome/window-main.c @@ -457,7 +457,7 @@ static void gnc_refresh_main_window_title() { GtkWidget *main_window; - Session *session; + GNCBook *book; gchar *filename; gchar *title; @@ -465,12 +465,9 @@ gnc_refresh_main_window_title() if (main_window == NULL) return; - session = gncGetCurrentSession(); + book = gncGetCurrentBook (); - if (session == NULL) - filename = _("Untitled"); - else - filename = xaccSessionGetFilePath(session); + filename = gnc_book_get_file_path (book); if ((filename == NULL) || (*filename == '\0')) filename = _("Untitled");