mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-18 05:06:21 +00:00
_win_printf dropped buffer append and render for any window in paged state, but only WIN_CHAT can recover lost messages via chatwin_db_history() on scroll-down. WIN_MUC, WIN_PRIVATE and WIN_AI have no such fallback, so incoming and outgoing messages were silently lost when the user was viewing history. Introduce log_database_can_recover_messages() to check whether the DB backend can replay messages (returns FALSE when PREF_DBLOG is "off", "redact", or no backend is active). Gate the WIN_CHAT early return in _win_printf() on this check: when recovery is impossible, fall through and append to the buffer so messages remain visible on scroll-down. Add a buffer-bottom reset in win_page_down() for non-chat windows. WIN_SCROLL_REACHED_BOTTOM is only set on the is_chat DB branch, so non-chat windows never clear paged on their own; reset paged and unread_msg when the last line of the buffer reaches the screen. Add missing scroll rendering for AI windows in the title bar draw function, ensuring AI windows display their scrolled state consistently with other window types. Remove the manual paged/unread_msg reset before printing the user message in cl_ev_send_ai_msg() -- it was a local workaround for the same drop and is no longer needed.
122 lines
5.1 KiB
C
122 lines
5.1 KiB
C
/*
|
|
* database.h
|
|
* vim: expandtab:ts=4:sts=4:sw=4
|
|
*
|
|
* Copyright (C) 2020 - 2025 Michael Vetter <jubalh@iodoru.org>
|
|
*
|
|
* This file is part of Profanity.
|
|
*
|
|
* Profanity 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Profanity 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 Profanity. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* In addition, as a special exception, the copyright holders give permission to
|
|
* link the code of portions of this program with the OpenSSL library under
|
|
* certain conditions as described in each individual source file, and
|
|
* distribute linked combinations including the two.
|
|
*
|
|
* You must obey the GNU General Public License in all respects for all of the
|
|
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
|
* may extend this exception to your version of the file(s), but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this exception
|
|
* statement from your version. If you delete this exception statement from all
|
|
* source files in the program, then also delete it here.
|
|
*
|
|
*/
|
|
|
|
#ifndef DATABASE_H
|
|
#define DATABASE_H
|
|
|
|
#include <glib.h>
|
|
#include "config/account.h"
|
|
#include "xmpp/xmpp.h"
|
|
|
|
#define MESSAGES_TO_RETRIEVE 100
|
|
|
|
typedef enum {
|
|
DB_RESPONSE_ERROR,
|
|
DB_RESPONSE_EMPTY,
|
|
DB_RESPONSE_SUCCESS
|
|
} db_history_result_t;
|
|
|
|
// Integrity verification issue levels
|
|
typedef enum {
|
|
INTEGRITY_ERROR,
|
|
INTEGRITY_WARNING,
|
|
INTEGRITY_INFO
|
|
} integrity_level_t;
|
|
|
|
// A single integrity issue found during verification
|
|
typedef struct
|
|
{
|
|
integrity_level_t level;
|
|
char* file;
|
|
int line;
|
|
char* message;
|
|
} integrity_issue_t;
|
|
|
|
void integrity_issue_free(integrity_issue_t* issue);
|
|
|
|
// Backend vtable: pluggable storage backends implement this interface
|
|
typedef struct db_backend_t
|
|
{
|
|
const char* name;
|
|
gboolean (*init)(ProfAccount* account);
|
|
void (*close)(void);
|
|
void (*add_incoming)(ProfMessage* message);
|
|
void (*add_outgoing_chat)(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
void (*add_outgoing_muc)(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
void (*add_outgoing_muc_pm)(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
db_history_result_t (*get_previous_chat)(const gchar* const contact_barejid, const gchar* start_time, const gchar* end_time, gboolean from_start, gboolean flip, GSList** result);
|
|
ProfMessage* (*get_limits_info)(const gchar* const contact_barejid, gboolean is_last);
|
|
GSList* (*verify_integrity)(const gchar* const contact_barejid);
|
|
} db_backend_t;
|
|
|
|
// Active backend (set during init based on PREF_DBLOG)
|
|
extern db_backend_t* active_db_backend;
|
|
|
|
// Backend registry
|
|
#ifdef HAVE_SQLITE
|
|
db_backend_t* db_backend_sqlite(void);
|
|
GSList* db_sqlite_list_contacts(void);
|
|
GSList* db_sqlite_get_all_chat(const gchar* const contact_barejid);
|
|
void db_sqlite_begin_transaction(void);
|
|
void db_sqlite_end_transaction(void);
|
|
void db_sqlite_rollback_transaction(void);
|
|
int db_sqlite_last_changes(void);
|
|
gboolean db_sqlite_is_open(void);
|
|
#endif
|
|
db_backend_t* db_backend_flatfile(void);
|
|
|
|
// Public API (dispatches to active_db_backend)
|
|
gboolean log_database_init(ProfAccount* account);
|
|
gboolean log_database_switch_backend(const char* new_backend);
|
|
void log_database_add_incoming(ProfMessage* message);
|
|
void log_database_add_outgoing_chat(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
void log_database_add_outgoing_muc(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
void log_database_add_outgoing_muc_pm(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
|
db_history_result_t log_database_get_previous_chat(const gchar* const contact_barejid, const gchar* start_time, const gchar* end_time, gboolean from_start, gboolean flip, GSList** result);
|
|
ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last);
|
|
void log_database_close(void);
|
|
GSList* log_database_verify_integrity(const gchar* const contact_barejid);
|
|
|
|
// FALSE if no backend, or PREF_DBLOG is "off" / "redact".
|
|
gboolean log_database_can_recover_messages(void);
|
|
|
|
// Cross-backend export/import (requires HAVE_SQLITE)
|
|
#ifdef HAVE_SQLITE
|
|
int log_database_export_to_flatfile(const gchar* const contact_jid);
|
|
int log_database_import_from_flatfile(const gchar* const contact_jid);
|
|
#endif
|
|
|
|
#endif // DATABASE_H
|