1 Commits

54 changed files with 461 additions and 1684 deletions

68
.github/workflows/theme-tests.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: Theme Tests
on:
push:
branches: [master, main]
paths:
- '.github/workflows/theme-tests.yml'
- 'meson.build'
- 'meson_options.txt'
- 'src/common/**'
- 'src/fe-gtk/meson.build'
- 'src/fe-gtk/theme/**'
pull_request:
branches: [master, main]
paths:
- '.github/workflows/theme-tests.yml'
- 'meson.build'
- 'meson_options.txt'
- 'src/common/**'
- 'src/fe-gtk/meson.build'
- 'src/fe-gtk/theme/**'
workflow_dispatch:
permissions:
contents: read
jobs:
theme_tests:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
with:
submodules: true
- name: Install dependencies
run: |
set -eux
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential \
meson \
ninja-build \
pkg-config \
gettext \
libgtk-3-dev \
libglib2.0-dev \
libdbus-glib-1-dev \
libcanberra-dev \
libarchive-dev \
libssl-dev \
xvfb
- name: Configure
run: |
set -eux
meson setup build-theme-tests \
-Dauto_features=disabled \
-Dplugin=false \
-Dtext-frontend=true
- name: Run theme tests
run: |
set -eux
xvfb-run -a env NO_AT_BRIDGE=1 GSETTINGS_BACKEND=memory \
meson test -C build-theme-tests --print-errorlogs \
--timeout-multiplier 2 \
'Theme Manager Dispatch Routing Tests'

View File

@@ -29,7 +29,7 @@ jobs:
- uses: actions/setup-python@v6 - uses: actions/setup-python@v6
with: with:
python-version: '3.14.3' python-version: '3.14.2'
architecture: ${{ matrix.arch }} architecture: ${{ matrix.arch }}
- name: Install Dependencies - name: Install Dependencies
@@ -62,16 +62,19 @@ jobs:
} }
} }
Download-WithRetry -Url https://github.com/jrsoftware/issrc/releases/download/is-6_7_1/innosetup-6.7.1.exe -OutFile deps\innosetup-unicode.exe Download-WithRetry -Url https://files.jrsoftware.org/is/6/innosetup-6.7.0.exe -OutFile deps\innosetup-unicode.exe
& deps\innosetup-unicode.exe /VERYSILENT | Out-Null & deps\innosetup-unicode.exe /VERYSILENT | Out-Null
Download-WithRetry -Url https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/idpsetup-1.5.1.exe -OutFile deps\idpsetup.exe
& deps\idpsetup.exe /VERYSILENT
Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre1/GTK3_Gvsbuild_zoitechat-2.18.0-pre1_${{ matrix.platform }}.7z -OutFile deps\gtk-${{ matrix.arch }}.7z Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre1/GTK3_Gvsbuild_zoitechat-2.18.0-pre1_${{ matrix.platform }}.7z -OutFile deps\gtk-${{ matrix.arch }}.7z
& 7z.exe x deps\gtk-${{ matrix.arch }}.7z -oC:\gtk-build\gtk\x64\release & 7z.exe x deps\gtk-${{ matrix.arch }}.7z -oC:\gtk-build\gtk\x64\release
Download-WithRetry -Url https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-hicolor-icon-theme-0.18-1-any.pkg.tar.zst -OutFile deps\hicolor-icon-theme.pkg.tar.zst Download-WithRetry -Url https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-hicolor-icon-theme-0.18-1-any.pkg.tar.zst -OutFile deps\hicolor-icon-theme.pkg.tar.zst
python -c "import tarfile,zstandard,pathlib;archive=pathlib.Path(r'deps\\hicolor-icon-theme.pkg.tar.zst');target=pathlib.Path(r'C:\\gtk-build\\gtk\\x64\\release');dctx=zstandard.ZstdDecompressor();f=archive.open('rb');reader=dctx.stream_reader(f);tf=tarfile.open(fileobj=reader,mode='r|');[tf.extract(m,path=target) for m in tf if m.name.startswith('mingw64/share/icons/hicolor/')];tf.close();reader.close();f.close()" python -c "import tarfile,zstandard,pathlib;archive=pathlib.Path(r'deps\\hicolor-icon-theme.pkg.tar.zst');target=pathlib.Path(r'C:\\gtk-build\\gtk\\x64\\release');dctx=zstandard.ZstdDecompressor();f=archive.open('rb');reader=dctx.stream_reader(f);tf=tarfile.open(fileobj=reader,mode='r|');[tf.extract(m,path=target) for m in tf if m.name.startswith('mingw64/share/icons/hicolor/')];tf.close();reader.close();f.close()"
Download-WithRetry -Url https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libarchive-3.8.6-1-any.pkg.tar.zst -OutFile deps\libarchive.pkg.tar.zst Download-WithRetry -Url https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libarchive-3.8.1-1-any.pkg.tar.zst -OutFile deps\libarchive.pkg.tar.zst
python -c "import tarfile,zstandard,pathlib;archive=pathlib.Path(r'deps\\libarchive.pkg.tar.zst');target=pathlib.Path(r'C:\\gtk-build\\gtk\\x64\\release');dctx=zstandard.ZstdDecompressor();f=archive.open('rb');reader=dctx.stream_reader(f);tf=tarfile.open(fileobj=reader,mode='r|');[tf.extract(m,path=target) for m in tf if m.name.startswith(('mingw64/include/archive','mingw64/lib/libarchive','mingw64/bin/libarchive'))];tf.close();reader.close();f.close()" python -c "import tarfile,zstandard,pathlib;archive=pathlib.Path(r'deps\\libarchive.pkg.tar.zst');target=pathlib.Path(r'C:\\gtk-build\\gtk\\x64\\release');dctx=zstandard.ZstdDecompressor();f=archive.open('rb');reader=dctx.stream_reader(f);tf=tarfile.open(fileobj=reader,mode='r|');[tf.extract(m,path=target) for m in tf if m.name.startswith(('mingw64/include/archive','mingw64/lib/libarchive','mingw64/bin/libarchive'))];tf.close();reader.close();f.close()"
if (Test-Path C:\gtk-build\gtk\x64\release\mingw64\share\icons\hicolor) { if (Test-Path C:\gtk-build\gtk\x64\release\mingw64\share\icons\hicolor) {
@@ -94,19 +97,19 @@ jobs:
Remove-Item -Path C:\gtk-build\gtk\x64\release\mingw64 -Recurse -Force Remove-Item -Path C:\gtk-build\gtk\x64\release\mingw64 -Recurse -Force
} }
Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre4/gendef20260315.7z -OutFile deps\gendef.7z Download-WithRetry -Url https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/gendef-20111031.7z -OutFile deps\gendef.7z
& 7z.exe x deps\gendef.7z -oC:\gtk-build & 7z.exe x deps\gendef.7z -oC:\gtk-build
Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre4/WinSparkle-20260315.7z -OutFile deps\WinSparkle.7z Download-WithRetry -Url https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/WinSparkle-20151011.7z -OutFile deps\WinSparkle.7z
& 7z.exe x deps\WinSparkle.7z -oC:\gtk-build\WinSparkle & 7z.exe x deps\WinSparkle.7z -oC:\gtk-build\WinSparkle
Download-WithRetry -Url https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre4/perl-5.42.0.1-${{ matrix.arch }}.7z -OutFile deps\perl-${{ matrix.arch }}.7z Download-WithRetry -Url https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/perl-5.20.0-${{ matrix.arch }}.7z -OutFile deps\perl-${{ matrix.arch }}.7z
& 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.42.0.1\${{ matrix.platform }} & 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.20\${{ matrix.platform }}
$pyRoot = $env:pythonLocation $pyRoot = $env:pythonLocation
if (-not $pyRoot) { $pyRoot = & python -c "import sys; print(sys.prefix)" } if (-not $pyRoot) { $pyRoot = & python -c "import sys; print(sys.prefix)" }
foreach ($pyDir in @("C:\gtk-build\python-3.14.3", "C:\gtk-build\python-3.14")) { foreach ($pyDir in @("C:\gtk-build\python-3.14.2", "C:\gtk-build\python-3.14")) {
New-Item -Path $pyDir -ItemType Directory -Force | Out-Null New-Item -Path $pyDir -ItemType Directory -Force | Out-Null
$target = Join-Path $pyDir "${{ matrix.platform }}" $target = Join-Path $pyDir "${{ matrix.platform }}"
if (Test-Path $target) { Remove-Item $target -Recurse -Force } if (Test-Path $target) { Remove-Item $target -Recurse -Force }
@@ -117,7 +120,7 @@ jobs:
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
set "PYTHON_DIR=C:\gtk-build\python-3.14.3\${{ matrix.platform }}" set "PYTHON_DIR=C:\gtk-build\python-3.14.2\${{ matrix.platform }}"
if not exist "%PYTHON_DIR%\libs\python314.lib" ( if not exist "%PYTHON_DIR%\libs\python314.lib" (
echo Missing %PYTHON_DIR%\libs\python314.lib echo Missing %PYTHON_DIR%\libs\python314.lib
dir "%PYTHON_DIR%\libs" dir "%PYTHON_DIR%\libs"

View File

@@ -1,15 +1,6 @@
ZoiteChat ChangeLog ZoiteChat ChangeLog
================= =================
2.18.0~pre4 (2026-03-15)
------------------------
- Fixed a regression where Ctrl+A could incorrectly mark you away instead of selecting all text.
- Fixed a crash when toggling the GUI with F9 or the menu toggle action.
- Fixed sidebar collapse behavior on fresh installs.
- Added multiline topic bar support with clickable URLs.
- Improved GTK selection styling so text selection is shown visually on topic and chat text box.
2.18.0~pre3 (2026-03-13) 2.18.0~pre3 (2026-03-13)
------------------------ ------------------------

View File

@@ -29,18 +29,6 @@
<id>zoitechat.desktop</id> <id>zoitechat.desktop</id>
</provides> </provides>
<releases> <releases>
<release date="2026-03-14" version="2.18.0~pre4">
<description>
<p>UI fixes, topic bar improvements, and selection styling updates:</p>
<ul>
<li>Fixed a regression where <code>Ctrl+A</code> could incorrectly mark you away instead of selecting all text.</li>
<li>Fixed a crash when toggling the GUI with <code>F9</code> or the menu toggle action.</li>
<li>Fixed sidebar collapse behavior on fresh installs.</li>
<li>Added multiline topic bar support with clickable URLs.</li>
<li>Improved GTK selection styling so text selection is shown visually in the topic bar and chat input box.</li>
</ul>
</description>
</release>
<release date="2026-03-13" version="2.18.0~pre3"> <release date="2026-03-13" version="2.18.0~pre3">
<description> <description>
<p>GTK3 theming, UI, and platform improvements:</p> <p>GTK3 theming, UI, and platform improvements:</p>

View File

@@ -1,5 +1,5 @@
project('zoitechat', 'c', project('zoitechat', 'c',
version: '2.18.0~pre4', version: '2.18.0~pre3',
meson_version: '>= 0.55.0', meson_version: '>= 0.55.0',
default_options: [ default_options: [
'c_std=c17', 'c_std=c17',

View File

@@ -12,7 +12,6 @@ depends=(
'glib2' 'glib2'
'gtk3' 'gtk3'
'iso-codes' 'iso-codes'
'libayatana-appindicator'
'libcanberra' 'libcanberra'
'lua' 'lua'
'openssl' 'openssl'
@@ -27,6 +26,7 @@ makedepends=(
'python' 'python'
) )
optdepends=( optdepends=(
'libayatana-appindicator: Ayatana/AppIndicator tray backend'
'pciutils: sysinfo plugin hardware detection details' 'pciutils: sysinfo plugin hardware detection details'
) )
provides=('zoitechat') provides=('zoitechat')

View File

@@ -45,22 +45,6 @@ endif
perl_ldflags = [] perl_ldflags = []
perl_rpath = '' perl_rpath = ''
foreach flag : ret.stdout().strip().split(' ') foreach flag : ret.stdout().strip().split(' ')
if flag.startswith('/') and '/libperl.' in flag
split = flag.split('/')
libperl_dir = ''
foreach part : split
if part != '' and not part.startswith('libperl.')
if libperl_dir == ''
libperl_dir = '/' + part
else
libperl_dir += '/' + part
endif
endif
endforeach
perl_ldflags += '-L' + libperl_dir
perl_ldflags += '-lperl'
continue
endif
if flag.startswith('-L') or flag.startswith('-l') if flag.startswith('-L') or flag.startswith('-l')
perl_ldflags += flag perl_ldflags += flag
endif endif

View File

@@ -19,7 +19,7 @@ else:
if not hasattr(sys, 'argv'): if not hasattr(sys, 'argv'):
sys.argv = ['<zoitechat>'] sys.argv = ['<zoitechat>']
VERSION = b'2.18.0~pre4' VERSION = b'2.18.0~pre3'
PLUGIN_NAME = ffi.new('char[]', b'Python') PLUGIN_NAME = ffi.new('char[]', b'Python')
PLUGIN_DESC = ffi.new('char[]', b'Python %d.%d scripting interface' % (sys.version_info[0], sys.version_info[1])) PLUGIN_DESC = ffi.new('char[]', b'Python %d.%d scripting interface' % (sys.version_info[0], sys.version_info[1]))
PLUGIN_VERSION = ffi.new('char[]', VERSION) PLUGIN_VERSION = ffi.new('char[]', VERSION)

View File

@@ -407,9 +407,6 @@ const struct prefs vars[] =
{"gui_autoopen_send", P_OFFINT (hex_gui_autoopen_send), TYPE_BOOL}, {"gui_autoopen_send", P_OFFINT (hex_gui_autoopen_send), TYPE_BOOL},
{"gui_chanlist_maxusers", P_OFFINT (hex_gui_chanlist_maxusers), TYPE_INT}, {"gui_chanlist_maxusers", P_OFFINT (hex_gui_chanlist_maxusers), TYPE_INT},
{"gui_chanlist_minusers", P_OFFINT (hex_gui_chanlist_minusers), TYPE_INT}, {"gui_chanlist_minusers", P_OFFINT (hex_gui_chanlist_minusers), TYPE_INT},
{"gui_chanlist_width_channel", P_OFFINT (hex_gui_chanlist_width_channel), TYPE_INT},
{"gui_chanlist_width_topic", P_OFFINT (hex_gui_chanlist_width_topic), TYPE_INT},
{"gui_chanlist_width_users", P_OFFINT (hex_gui_chanlist_width_users), TYPE_INT},
{"gui_compact", P_OFFINT (hex_gui_compact), TYPE_BOOL}, {"gui_compact", P_OFFINT (hex_gui_compact), TYPE_BOOL},
{"gui_dialog_height", P_OFFINT (hex_gui_dialog_height), TYPE_INT}, {"gui_dialog_height", P_OFFINT (hex_gui_dialog_height), TYPE_INT},
{"gui_dialog_left", P_OFFINT (hex_gui_dialog_left), TYPE_INT}, {"gui_dialog_left", P_OFFINT (hex_gui_dialog_left), TYPE_INT},
@@ -469,8 +466,6 @@ const struct prefs vars[] =
{"gui_ulist_hide", P_OFFINT (hex_gui_ulist_hide), TYPE_BOOL}, {"gui_ulist_hide", P_OFFINT (hex_gui_ulist_hide), TYPE_BOOL},
{"gui_ulist_icons", P_OFFINT (hex_gui_ulist_icons), TYPE_BOOL}, {"gui_ulist_icons", P_OFFINT (hex_gui_ulist_icons), TYPE_BOOL},
{"gui_ulist_pos", P_OFFINT (hex_gui_ulist_pos), TYPE_INT}, {"gui_ulist_pos", P_OFFINT (hex_gui_ulist_pos), TYPE_INT},
{"gui_ulist_nick_width", P_OFFINT (hex_gui_ulist_nick_width), TYPE_INT},
{"gui_ulist_host_width", P_OFFINT (hex_gui_ulist_host_width), TYPE_INT},
{"gui_ulist_show_hosts", P_OFFINT(hex_gui_ulist_show_hosts), TYPE_BOOL}, {"gui_ulist_show_hosts", P_OFFINT(hex_gui_ulist_show_hosts), TYPE_BOOL},
{"gui_ulist_sort", P_OFFINT (hex_gui_ulist_sort), TYPE_INT}, {"gui_ulist_sort", P_OFFINT (hex_gui_ulist_sort), TYPE_INT},
{"gui_ulist_style", P_OFFINT (hex_gui_ulist_style), TYPE_BOOL}, {"gui_ulist_style", P_OFFINT (hex_gui_ulist_style), TYPE_BOOL},
@@ -829,9 +824,6 @@ load_default_config(void)
prefs.hex_flood_msg_time = 30; prefs.hex_flood_msg_time = 30;
prefs.hex_gui_chanlist_maxusers = 9999; prefs.hex_gui_chanlist_maxusers = 9999;
prefs.hex_gui_chanlist_minusers = 5; prefs.hex_gui_chanlist_minusers = 5;
prefs.hex_gui_chanlist_width_channel = 0;
prefs.hex_gui_chanlist_width_topic = 0;
prefs.hex_gui_chanlist_width_users = 0;
prefs.hex_gui_dialog_height = 256; prefs.hex_gui_dialog_height = 256;
prefs.hex_gui_dialog_width = 500; prefs.hex_gui_dialog_width = 500;
prefs.hex_gui_lagometer = 1; prefs.hex_gui_lagometer = 1;
@@ -845,8 +837,6 @@ load_default_config(void)
prefs.hex_gui_tab_trunc = 20; prefs.hex_gui_tab_trunc = 20;
prefs.hex_gui_throttlemeter = 1; prefs.hex_gui_throttlemeter = 1;
prefs.hex_gui_ulist_pos = 3; prefs.hex_gui_ulist_pos = 3;
prefs.hex_gui_ulist_nick_width = 0;
prefs.hex_gui_ulist_host_width = 0;
prefs.hex_gui_win_height = 400; prefs.hex_gui_win_height = 400;
prefs.hex_gui_win_width = 640; prefs.hex_gui_win_width = 640;
prefs.hex_irc_ban_type = 1; prefs.hex_irc_ban_type = 1;
@@ -1019,51 +1009,15 @@ load_config (void)
return 0; return 0;
} }
static int
save_config_write_to_fd (int fh)
{
int i;
if (!cfg_put_str (fh, "version", PACKAGE_VERSION))
return 0;
i = 0;
do
{
switch (vars[i].type)
{
case TYPE_STR:
if (!cfg_put_str (fh, vars[i].name, (char *) &prefs + vars[i].offset))
return 0;
break;
case TYPE_INT:
case TYPE_BOOL:
if (!cfg_put_int (fh, *((int *) &prefs + vars[i].offset), vars[i].name))
return 0;
}
if (vars[i].after_update != NULL)
vars[i].after_update();
i++;
}
while (vars[i].name);
return 1;
}
int int
save_config_prepare (char **temp_path) save_config (void)
{ {
int fh; int fh, i;
char *config; char *config, *new_config;
char *new_config;
if (check_config_dir () != 0) if (check_config_dir () != 0)
make_config_dirs (); make_config_dirs ();
if (!temp_path)
return 0;
config = default_file (); config = default_file ();
new_config = g_strconcat (config, ".new", NULL); new_config = g_strconcat (config, ".new", NULL);
@@ -1074,67 +1028,63 @@ save_config_prepare (char **temp_path)
return 0; return 0;
} }
if (!save_config_write_to_fd (fh)) if (!cfg_put_str (fh, "version", PACKAGE_VERSION))
{ {
close (fh); close (fh);
g_free (new_config); g_free (new_config);
return 0; return 0;
} }
i = 0;
do
{
switch (vars[i].type)
{
case TYPE_STR:
if (!cfg_put_str (fh, vars[i].name, (char *) &prefs + vars[i].offset))
{
close (fh);
g_free (new_config);
return 0;
}
break;
case TYPE_INT:
case TYPE_BOOL:
if (!cfg_put_int (fh, *((int *) &prefs + vars[i].offset), vars[i].name))
{
close (fh);
g_free (new_config);
return 0;
}
}
if (vars[i].after_update != NULL)
{
vars[i].after_update();
}
i++;
}
while (vars[i].name);
if (close (fh) == -1) if (close (fh) == -1)
{ {
g_free (new_config); g_free (new_config);
return 0; return 0;
} }
*temp_path = new_config;
return 1;
}
int
save_config_finalize (const char *temp_path)
{
char *config;
if (!temp_path)
return 0;
config = default_file ();
#ifdef WIN32 #ifdef WIN32
g_unlink (config); g_unlink (config); /* win32 can't rename to an existing file */
#endif #endif
if (g_rename (temp_path, config) == -1) if (g_rename (new_config, config) == -1)
{
g_free (new_config);
return 0; return 0;
}
g_free (new_config);
return 1; return 1;
} }
void
save_config_discard (const char *temp_path)
{
if (!temp_path)
return;
g_unlink (temp_path);
}
int
save_config (void)
{
char *temp_path = NULL;
int result;
if (!save_config_prepare (&temp_path))
return 0;
result = save_config_finalize (temp_path);
if (!result)
save_config_discard (temp_path);
g_free (temp_path);
return result;
}
static void static void
set_showval (session *sess, const struct prefs *var, char *tbuf) set_showval (session *sess, const struct prefs *var, char *tbuf)
{ {

View File

@@ -43,9 +43,6 @@ int make_config_dirs (void);
int make_dcc_dirs (void); int make_dcc_dirs (void);
int load_config (void); int load_config (void);
int save_config (void); int save_config (void);
int save_config_prepare (char **temp_path);
int save_config_finalize (const char *temp_path);
void save_config_discard (const char *temp_path);
void list_free (GSList ** list); void list_free (GSList ** list);
void list_loadconf (char *file, GSList ** list, char *defaultconf); void list_loadconf (char *file, GSList ** list, char *defaultconf);
int list_delentry (GSList ** list, char *name); int list_delentry (GSList ** list, char *name);

View File

@@ -44,20 +44,11 @@ typedef struct
char *icon; /* filename */ char *icon; /* filename */
} menu_entry; } menu_entry;
typedef struct
{
gboolean success;
gboolean partial_failure;
gboolean config_failed;
gboolean theme_failed;
} fe_preferences_save_result;
int fe_args (int argc, char *argv[]); int fe_args (int argc, char *argv[]);
void fe_init (void); void fe_init (void);
void fe_main (void); void fe_main (void);
void fe_cleanup (void); void fe_cleanup (void);
void fe_exit (void); void fe_exit (void);
fe_preferences_save_result fe_preferences_persistence_save_all (void);
int fe_timeout_add (int interval, void *callback, void *userdata); int fe_timeout_add (int interval, void *callback, void *userdata);
int fe_timeout_add_seconds (int interval, void *callback, void *userdata); int fe_timeout_add_seconds (int interval, void *callback, void *userdata);
void fe_timeout_remove (int tag); void fe_timeout_remove (int tag);

View File

@@ -292,13 +292,7 @@ match_host (const char *word, int *start, int *end)
static gboolean static gboolean
match_host6 (const char *word, int *start, int *end) match_host6 (const char *word, int *start, int *end)
{ {
if (!regex_match (re_host6 (), word, start, end)) return regex_match (re_host6 (), word, start, end);
return FALSE;
if (word[*start] != '[')
return FALSE;
return TRUE;
} }
static gboolean static gboolean
@@ -378,65 +372,41 @@ url_last (int *lstart, int *lend)
return lasttype; return lasttype;
} }
static gboolean
match_has_valid_context (const char *word, int start, int end)
{
if (start > 0)
{
char prev = word[start - 1];
if (g_ascii_isalnum ((guchar)prev) || prev == '_' || prev == '-')
return FALSE;
}
if (word[end] != '\0')
{
char next = word[end];
if (g_ascii_isalnum ((guchar)next) || next == '_')
return FALSE;
}
return TRUE;
}
static gboolean static gboolean
regex_match (const GRegex *re, const char *word, int *start, int *end) regex_match (const GRegex *re, const char *word, int *start, int *end)
{ {
GMatchInfo *gmi; GMatchInfo *gmi;
gboolean found = FALSE;
int mstart;
int mend;
g_regex_match (re, word, 0, &gmi); g_regex_match (re, word, 0, &gmi);
if (!g_match_info_matches (gmi))
{
g_match_info_free (gmi);
return FALSE;
}
while (g_match_info_matches (gmi)) while (g_match_info_matches (gmi))
{ {
g_match_info_fetch_pos (gmi, 0, &mstart, &mend); g_match_info_fetch_pos (gmi, 0, start, end);
if (match_has_valid_context (word, mstart, mend))
{
*start = mstart;
*end = mend;
found = TRUE;
}
g_match_info_next (gmi, NULL); g_match_info_next (gmi, NULL);
} }
g_match_info_free (gmi); g_match_info_free (gmi);
return found; return TRUE;
} }
/* Miscellaneous description --- */ /* Miscellaneous description --- */
#define DOMAIN_LABEL "[\\pL\\pN](?:[-\\pL\\pN]{0,61}[\\pL\\pN])?" #define DOMAIN "[_\\pL\\pN\\pS][-_\\pL\\pN\\pS]*(\\.[-_\\pL\\pN\\pS]+)*"
#define DOMAIN DOMAIN_LABEL "(\\." DOMAIN_LABEL ")*" #define TLD "\\.[\\pL][-\\pL\\pN]*[\\pL]"
#define TLD "\\.[\\pL](?:[-\\pL\\pN]*[\\pL\\pN])?" #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
#define IPADDR "(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}"
#define IPV6GROUP "([0-9a-f]{0,4})" #define IPV6GROUP "([0-9a-f]{0,4})"
#define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \ #define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \
"|(" IPV6GROUP "(:" IPV6GROUP ")*:(:" IPV6GROUP ")+))" /* with :: compression */ "|(" IPV6GROUP "(:" IPV6GROUP ")*:(:" IPV6GROUP ")+))" /* with :: compression */
#define HOST "(" DOMAIN TLD "|" IPADDR "|" IPV6ADDR ")" #define HOST "(" DOMAIN TLD "|" IPADDR "|" IPV6ADDR ")"
/* In urls the IPv6 must be enclosed in square brackets */ /* In urls the IPv6 must be enclosed in square brackets */
#define HOST_URL "(" DOMAIN TLD "|" IPADDR "|" "\\[" IPV6ADDR "\\]" ")" #define HOST_URL "(" DOMAIN TLD "|" IPADDR "|" "\\[" IPV6ADDR "\\]" ")"
#define HOST_URL_OPT_TLD HOST_URL #define HOST_URL_OPT_TLD "(" DOMAIN "|" HOST_URL ")"
#define PORT "(:[1-9][0-9]{0,4})" #define PORT "(:[1-9][0-9]{0,4})"
#define OPT_PORT "(" PORT ")?" #define OPT_PORT "(" PORT ")?"

View File

@@ -1104,18 +1104,7 @@ zoitechat_exit (void)
plugin_kill_all (); plugin_kill_all ();
fe_cleanup (); fe_cleanup ();
{ save_config ();
fe_preferences_save_result save_result;
save_result = fe_preferences_persistence_save_all ();
if (!save_result.success)
{
if (save_result.partial_failure || (!save_result.config_failed && save_result.theme_failed))
g_printerr ("Could not fully save preferences. zoitechat.conf was written, but colors.conf failed.\n");
else
g_printerr ("Could not save zoitechat.conf.\n");
}
}
if (prefs.save_pevents) if (prefs.save_pevents)
{ {
pevent_save (NULL); pevent_save (NULL);

View File

@@ -248,9 +248,6 @@ struct zoitechatprefs
int hex_flood_msg_time; int hex_flood_msg_time;
int hex_gui_chanlist_maxusers; int hex_gui_chanlist_maxusers;
int hex_gui_chanlist_minusers; int hex_gui_chanlist_minusers;
int hex_gui_chanlist_width_channel;
int hex_gui_chanlist_width_topic;
int hex_gui_chanlist_width_users;
int hex_gui_dialog_height; int hex_gui_dialog_height;
int hex_gui_dialog_left; int hex_gui_dialog_left;
int hex_gui_dialog_top; int hex_gui_dialog_top;
@@ -272,8 +269,6 @@ struct zoitechatprefs
int hex_gui_transparency; int hex_gui_transparency;
int hex_gui_throttlemeter; int hex_gui_throttlemeter;
int hex_gui_ulist_pos; int hex_gui_ulist_pos;
int hex_gui_ulist_nick_width;
int hex_gui_ulist_host_width;
int hex_gui_ulist_sort; int hex_gui_ulist_sort;
int hex_gui_url_mod; int hex_gui_url_mod;
int hex_gui_win_height; int hex_gui_win_height;

View File

@@ -153,7 +153,7 @@ ascii_open (void)
gtk_widget_set_size_request (but, 28, -1); gtk_widget_set_size_request (but, 28, -1);
g_signal_connect (G_OBJECT (but), "clicked", g_signal_connect (G_OBJECT (but), "clicked",
G_CALLBACK (ascii_click), NULL); G_CALLBACK (ascii_click), NULL);
g_signal_connect (G_OBJECT (but), "enter-notify-event", g_signal_connect (G_OBJECT (but), "enter_notify_event",
G_CALLBACK (ascii_enter), label); G_CALLBACK (ascii_enter), label);
gtk_box_pack_start (GTK_BOX (hbox), but, 0, 0, 0); gtk_box_pack_start (GTK_BOX (hbox), but, 0, 0, 0);
gtk_widget_show (but); gtk_widget_show (but);

View File

@@ -74,19 +74,6 @@ chanlistrow;
#define GET_MODEL(xserv) (gtk_tree_view_get_model(GTK_TREE_VIEW(xserv->gui->chanlist_list))) #define GET_MODEL(xserv) (gtk_tree_view_get_model(GTK_TREE_VIEW(xserv->gui->chanlist_list)))
#define CHANLIST_COL_WIDTH_MIN_CHANNEL 60
#define CHANLIST_COL_WIDTH_MIN_USERS 40
#define CHANLIST_COL_WIDTH_MIN_TOPIC 60
static int
chanlist_clamp_width (int width, int min_width)
{
if (width < min_width)
return min_width;
return width;
}
static void static void
chanlist_set_label_alignment (GtkWidget *widget) chanlist_set_label_alignment (GtkWidget *widget)
{ {
@@ -521,72 +508,36 @@ chanlist_match_topic_button_toggled (GtkWidget * wid, server *serv)
serv->gui->chanlist_match_wants_topic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid)); serv->gui->chanlist_match_wants_topic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid));
} }
static GSList *
chanlist_get_selection (server *serv, int column)
{
GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (serv->gui->chanlist_list));
GtkTreeModel *model = GET_MODEL (serv);
GList *rows;
GList *cur;
GSList *result = NULL;
rows = gtk_tree_selection_get_selected_rows (sel, &model);
for (cur = rows; cur != NULL; cur = cur->next)
{
GtkTreeIter iter;
char *value;
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)cur->data))
{
gtk_tree_model_get (model, &iter, column, &value, -1);
result = g_slist_prepend (result, value);
}
}
g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
return g_slist_reverse (result);
}
static char * static char *
chanlist_get_selected (server *serv, gboolean get_topic) chanlist_get_selected (server *serv, gboolean get_topic)
{ {
GSList *selection = chanlist_get_selection (serv, get_topic ? COL_TOPIC : COL_CHANNEL); char *chan;
char *value; GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (serv->gui->chanlist_list));
GtkTreeModel *model;
GtkTreeIter iter;
if (!selection) if (!gtk_tree_selection_get_selected (sel, &model, &iter))
return NULL; return NULL;
value = selection->data; gtk_tree_model_get (model, &iter, get_topic ? COL_TOPIC : COL_CHANNEL, &chan, -1);
selection->data = NULL; return chan;
g_slist_free_full (selection, g_free);
return value;
} }
static void static void
chanlist_join (GtkWidget * wid, server *serv) chanlist_join (GtkWidget * wid, server *serv)
{ {
char tbuf[CHANLEN + 6]; char tbuf[CHANLEN + 6];
GSList *selection; char *chan = chanlist_get_selected (serv, FALSE);
GSList *item; if (chan)
gboolean joined = FALSE;
selection = chanlist_get_selection (serv, COL_CHANNEL);
for (item = selection; item != NULL; item = item->next)
{ {
char *chan = item->data; if (serv->connected && (strcmp (chan, "*") != 0))
if (serv->connected && strcmp (chan, "*") != 0)
{ {
g_snprintf (tbuf, sizeof (tbuf), "join %s", chan); g_snprintf (tbuf, sizeof (tbuf), "join %s", chan);
handle_command (serv->server_session, tbuf, FALSE); handle_command (serv->server_session, tbuf, FALSE);
joined = TRUE; } else
}
}
if (!joined && selection)
gdk_display_beep (gdk_display_get_default ()); gdk_display_beep (gdk_display_get_default ());
g_free (chan);
g_slist_free_full (selection, g_free); }
} }
static void static void
@@ -663,8 +614,7 @@ chanlist_minusers (GtkSpinButton *wid, server *serv)
{ {
serv->gui->chanlist_minusers = gtk_spin_button_get_value_as_int (wid); serv->gui->chanlist_minusers = gtk_spin_button_get_value_as_int (wid);
prefs.hex_gui_chanlist_minusers = serv->gui->chanlist_minusers; prefs.hex_gui_chanlist_minusers = serv->gui->chanlist_minusers;
if (!save_config ()) save_config();
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
if (serv->gui->chanlist_minusers < serv->gui->chanlist_minusers_downloaded) if (serv->gui->chanlist_minusers < serv->gui->chanlist_minusers_downloaded)
{ {
@@ -686,8 +636,7 @@ chanlist_maxusers (GtkSpinButton *wid, server *serv)
{ {
serv->gui->chanlist_maxusers = gtk_spin_button_get_value_as_int (wid); serv->gui->chanlist_maxusers = gtk_spin_button_get_value_as_int (wid);
prefs.hex_gui_chanlist_maxusers = serv->gui->chanlist_maxusers; prefs.hex_gui_chanlist_maxusers = serv->gui->chanlist_maxusers;
if (!save_config ()) save_config();
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
} }
static void static void
@@ -707,47 +656,23 @@ chanlist_menu_destroy (GtkWidget *menu, gpointer userdata)
static void static void
chanlist_copychannel (GtkWidget *item, server *serv) chanlist_copychannel (GtkWidget *item, server *serv)
{ {
GSList *selection = chanlist_get_selection (serv, COL_CHANNEL); char *chan = chanlist_get_selected (serv, FALSE);
GSList *cur; if (chan)
GString *text;
if (!selection)
return;
text = g_string_new ("");
for (cur = selection; cur != NULL; cur = cur->next)
{ {
if (text->len) gtkutil_copy_to_clipboard (item, NULL, chan);
g_string_append_c (text, '\n'); g_free (chan);
g_string_append (text, (char *)cur->data);
} }
gtkutil_copy_to_clipboard (item, NULL, text->str);
g_string_free (text, TRUE);
g_slist_free_full (selection, g_free);
} }
static void static void
chanlist_copytopic (GtkWidget *item, server *serv) chanlist_copytopic (GtkWidget *item, server *serv)
{ {
GSList *selection = chanlist_get_selection (serv, COL_TOPIC); char *topic = chanlist_get_selected (serv, TRUE);
GSList *cur; if (topic)
GString *text;
if (!selection)
return;
text = g_string_new ("");
for (cur = selection; cur != NULL; cur = cur->next)
{ {
if (text->len) gtkutil_copy_to_clipboard (item, NULL, topic);
g_string_append_c (text, '\n'); g_free (topic);
g_string_append (text, (char *)cur->data);
} }
gtkutil_copy_to_clipboard (item, NULL, text->str);
g_string_free (text, TRUE);
g_slist_free_full (selection, g_free);
} }
static gboolean static gboolean
@@ -764,12 +689,10 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)
if (!gtk_tree_view_get_path_at_pos (tree, event->x, event->y, &path, 0, 0, 0)) if (!gtk_tree_view_get_path_at_pos (tree, event->x, event->y, &path, 0, 0, 0))
return FALSE; return FALSE;
/* select what they right-clicked on */
sel = gtk_tree_view_get_selection (tree); sel = gtk_tree_view_get_selection (tree);
if (!gtk_tree_selection_path_is_selected (sel, path))
{
gtk_tree_selection_unselect_all (sel); gtk_tree_selection_unselect_all (sel);
gtk_tree_selection_select_path (sel, path); gtk_tree_selection_select_path (sel, path);
}
gtk_tree_path_free (path); gtk_tree_path_free (path);
menu = gtk_menu_new (); menu = gtk_menu_new ();
@@ -818,26 +741,6 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)
static void static void
chanlist_destroy_widget (GtkWidget *wid, server *serv) chanlist_destroy_widget (GtkWidget *wid, server *serv)
{ {
GtkTreeViewColumn *column;
column = gtk_tree_view_get_column (GTK_TREE_VIEW (serv->gui->chanlist_list), COL_CHANNEL);
if (column)
prefs.hex_gui_chanlist_width_channel =
chanlist_clamp_width (gtk_tree_view_column_get_width (column), CHANLIST_COL_WIDTH_MIN_CHANNEL);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (serv->gui->chanlist_list), COL_USERS);
if (column)
prefs.hex_gui_chanlist_width_users =
chanlist_clamp_width (gtk_tree_view_column_get_width (column), CHANLIST_COL_WIDTH_MIN_USERS);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (serv->gui->chanlist_list), COL_TOPIC);
if (column)
prefs.hex_gui_chanlist_width_topic =
chanlist_clamp_width (gtk_tree_view_column_get_width (column), CHANLIST_COL_WIDTH_MIN_TOPIC);
if (!save_config ())
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
custom_list_clear ((CustomList *)GET_MODEL (serv)); custom_list_clear ((CustomList *)GET_MODEL (serv));
chanlist_data_free (serv); chanlist_data_free (serv);
@@ -928,8 +831,7 @@ chanlist_opengui (server *serv, int do_refresh)
if (prefs.hex_gui_chanlist_minusers < 1 || prefs.hex_gui_chanlist_minusers > 999999) if (prefs.hex_gui_chanlist_minusers < 1 || prefs.hex_gui_chanlist_minusers > 999999)
{ {
prefs.hex_gui_chanlist_minusers = 5; prefs.hex_gui_chanlist_minusers = 5;
if (!save_config ()) save_config();
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
} }
serv->gui->chanlist_minusers = prefs.hex_gui_chanlist_minusers; serv->gui->chanlist_minusers = prefs.hex_gui_chanlist_minusers;
@@ -940,8 +842,7 @@ chanlist_opengui (server *serv, int do_refresh)
if (prefs.hex_gui_chanlist_maxusers < 1 || prefs.hex_gui_chanlist_maxusers > 999999) if (prefs.hex_gui_chanlist_maxusers < 1 || prefs.hex_gui_chanlist_maxusers > 999999)
{ {
prefs.hex_gui_chanlist_maxusers = 9999; prefs.hex_gui_chanlist_maxusers = 9999;
if (!save_config ()) save_config();
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
} }
serv->gui->chanlist_maxusers = prefs.hex_gui_chanlist_maxusers; serv->gui->chanlist_maxusers = prefs.hex_gui_chanlist_maxusers;
@@ -969,7 +870,7 @@ chanlist_opengui (server *serv, int do_refresh)
GTK_SHADOW_IN); GTK_SHADOW_IN);
serv->gui->chanlist_list = view; serv->gui->chanlist_list = view;
g_signal_connect (G_OBJECT (view), "row-activated", g_signal_connect (G_OBJECT (view), "row_activated",
G_CALLBACK (chanlist_dclick_cb), serv); G_CALLBACK (chanlist_dclick_cb), serv);
g_signal_connect (G_OBJECT (view), "button-press-event", g_signal_connect (G_OBJECT (view), "button-press-event",
G_CALLBACK (chanlist_button_cb), serv); G_CALLBACK (chanlist_button_cb), serv);
@@ -977,39 +878,7 @@ chanlist_opengui (server *serv, int do_refresh)
chanlist_add_column (view, COL_CHANNEL, 96, _("Channel"), FALSE); chanlist_add_column (view, COL_CHANNEL, 96, _("Channel"), FALSE);
chanlist_add_column (view, COL_USERS, 50, _("Users"), TRUE); chanlist_add_column (view, COL_USERS, 50, _("Users"), TRUE);
chanlist_add_column (view, COL_TOPIC, 50, _("Topic"), FALSE); chanlist_add_column (view, COL_TOPIC, 50, _("Topic"), FALSE);
if (prefs.hex_gui_chanlist_width_channel > 0)
{
GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_CHANNEL);
if (column)
gtk_tree_view_column_set_fixed_width (column,
chanlist_clamp_width (prefs.hex_gui_chanlist_width_channel, CHANLIST_COL_WIDTH_MIN_CHANNEL));
}
if (prefs.hex_gui_chanlist_width_users > 0)
{
GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_USERS);
if (column)
{
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (column,
chanlist_clamp_width (prefs.hex_gui_chanlist_width_users, CHANLIST_COL_WIDTH_MIN_USERS));
gtk_tree_view_column_set_resizable (column, FALSE);
}
}
if (prefs.hex_gui_chanlist_width_topic > 0)
{
GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_TOPIC);
if (column)
{
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (column,
chanlist_clamp_width (prefs.hex_gui_chanlist_width_topic, CHANLIST_COL_WIDTH_MIN_TOPIC));
}
}
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL); gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), GTK_SELECTION_MULTIPLE);
/* this is a speed up, but no horizontal scrollbar :( */ /* this is a speed up, but no horizontal scrollbar :( */
/*gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);*/ /*gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);*/
gtk_widget_show (view); gtk_widget_show (view);
@@ -1067,7 +936,7 @@ chanlist_opengui (server *serv, int do_refresh)
wid = gtk_spin_button_new_with_range (1, 999999, 1); wid = gtk_spin_button_new_with_range (1, 999999, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid), gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid),
serv->gui->chanlist_minusers); serv->gui->chanlist_minusers);
g_signal_connect (G_OBJECT (wid), "value-changed", g_signal_connect (G_OBJECT (wid), "value_changed",
G_CALLBACK (chanlist_minusers), serv); G_CALLBACK (chanlist_minusers), serv);
gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0); gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);
gtk_widget_show (wid); gtk_widget_show (wid);
@@ -1080,7 +949,7 @@ chanlist_opengui (server *serv, int do_refresh)
wid = gtk_spin_button_new_with_range (1, 999999, 1); wid = gtk_spin_button_new_with_range (1, 999999, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid), gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid),
serv->gui->chanlist_maxusers); serv->gui->chanlist_maxusers);
g_signal_connect (G_OBJECT (wid), "value-changed", g_signal_connect (G_OBJECT (wid), "value_changed",
G_CALLBACK (chanlist_maxusers), serv); G_CALLBACK (chanlist_maxusers), serv);
gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0); gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);
gtk_widget_show (wid); gtk_widget_show (wid);

View File

@@ -371,7 +371,7 @@ make_sbutton (GtkArrowType type, void *click_cb, void *userdata)
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (G_OBJECT (button), "clicked", g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (click_cb), userdata); G_CALLBACK (click_cb), userdata);
g_signal_connect (G_OBJECT (button), "scroll-event", g_signal_connect (G_OBJECT (button), "scroll_event",
G_CALLBACK (tab_scroll_cb), userdata); G_CALLBACK (tab_scroll_cb), userdata);
gtk_widget_show (arrow); gtk_widget_show (arrow);
@@ -395,7 +395,7 @@ cv_tabs_init (chanview *cv)
outer = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0); outer = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
} }
((tabview *)cv)->outer = outer; ((tabview *)cv)->outer = outer;
g_signal_connect (G_OBJECT (outer), "size-allocate", g_signal_connect (G_OBJECT (outer), "size_allocate",
G_CALLBACK (cv_tabs_sizealloc), cv); G_CALLBACK (cv_tabs_sizealloc), cv);
gtk_widget_show (outer); gtk_widget_show (outer);
@@ -405,7 +405,7 @@ cv_tabs_init (chanview *cv)
gtk_widget_set_size_request (viewport, -1, 1); gtk_widget_set_size_request (viewport, -1, 1);
else else
gtk_widget_set_size_request (viewport, 1, -1); gtk_widget_set_size_request (viewport, 1, -1);
g_signal_connect (G_OBJECT (viewport), "scroll-event", g_signal_connect (G_OBJECT (viewport), "scroll_event",
G_CALLBACK (tab_scroll_cb), cv); G_CALLBACK (tab_scroll_cb), cv);
gtk_box_pack_start (GTK_BOX (outer), viewport, 1, 1, 0); gtk_box_pack_start (GTK_BOX (outer), viewport, 1, 1, 0);
gtk_widget_show (viewport); gtk_widget_show (viewport);
@@ -671,12 +671,12 @@ cv_tabs_add (chanview *cv, chan *ch, char *name, GtkTreeIter *parent)
gtk_widget_set_name (but, "zoitechat-tab"); gtk_widget_set_name (but, "zoitechat-tab");
g_object_set_data (G_OBJECT (but), "c", ch); g_object_set_data (G_OBJECT (but), "c", ch);
/* used to trap right-clicks */ /* used to trap right-clicks */
g_signal_connect (G_OBJECT (but), "button-press-event", g_signal_connect (G_OBJECT (but), "button_press_event",
G_CALLBACK (tab_click_cb), ch); G_CALLBACK (tab_click_cb), ch);
/* avoid prelights */ /* avoid prelights */
g_signal_connect (G_OBJECT (but), "enter-notify-event", g_signal_connect (G_OBJECT (but), "enter_notify_event",
G_CALLBACK (tab_ignore_cb), NULL); G_CALLBACK (tab_ignore_cb), NULL);
g_signal_connect (G_OBJECT (but), "leave-notify-event", g_signal_connect (G_OBJECT (but), "leave_notify_event",
G_CALLBACK (tab_ignore_cb), NULL); G_CALLBACK (tab_ignore_cb), NULL);
g_signal_connect (G_OBJECT (but), "pressed", g_signal_connect (G_OBJECT (but), "pressed",
G_CALLBACK (tab_pressed_cb), ch); G_CALLBACK (tab_pressed_cb), ch);

View File

@@ -131,7 +131,6 @@ cv_tree_init (chanview *cv)
GTK_SHADOW_IN); GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win), gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (win), 1);
gtk_container_add (GTK_CONTAINER (cv->box), win); gtk_container_add (GTK_CONTAINER (cv->box), win);
gtk_widget_show (win); gtk_widget_show (win);
@@ -166,32 +165,30 @@ cv_tree_init (chanview *cv)
gtk_container_add (GTK_CONTAINER (win), view); gtk_container_add (GTK_CONTAINER (win), view);
col = gtk_tree_view_column_new(); col = gtk_tree_view_column_new();
/* icon column */
if (cv->use_icons) if (cv->use_icons)
{ {
renderer = gtk_cell_renderer_pixbuf_new (); renderer = gtk_cell_renderer_pixbuf_new ();
if (prefs.hex_gui_compact) if (prefs.hex_gui_compact)
g_object_set (G_OBJECT (renderer), "ypad", 0, NULL); g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
gtk_tree_view_column_pack_start (col, renderer, FALSE); gtk_tree_view_column_pack_start(col, renderer, FALSE);
gtk_tree_view_column_set_attributes (col, renderer, "pixbuf", COL_PIXBUF, NULL); gtk_tree_view_column_set_attributes (col, renderer, "pixbuf", COL_PIXBUF, NULL);
} }
/* main column */
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
if (prefs.hex_gui_compact) if (prefs.hex_gui_compact)
g_object_set (G_OBJECT (renderer), "ypad", 0, NULL); g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1); gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
gtk_tree_view_column_pack_start (col, renderer, TRUE); gtk_tree_view_column_pack_start(col, renderer, TRUE);
gtk_tree_view_column_set_attributes (col, renderer, gtk_tree_view_column_set_attributes (col, renderer,
"text", COL_NAME, "text", COL_NAME,
"attributes", COL_ATTR, "attributes", COL_ATTR,
"underline", COL_UNDERLINE, "underline", COL_UNDERLINE,
NULL); NULL);
gtk_tree_view_column_set_expand (col, TRUE); gtk_tree_view_column_set_expand (col, TRUE);
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
gtk_tree_view_column_set_min_width (col, 1);
gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view), col);
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (view))), g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (view))),
"changed", G_CALLBACK (cv_tree_sel_cb), cv); "changed", G_CALLBACK (cv_tree_sel_cb), cv);
@@ -199,20 +196,20 @@ cv_tree_init (chanview *cv)
G_CALLBACK (cv_tree_click_cb), cv); G_CALLBACK (cv_tree_click_cb), cv);
g_signal_connect (G_OBJECT (view), "row-activated", g_signal_connect (G_OBJECT (view), "row-activated",
G_CALLBACK (cv_tree_activated_cb), NULL); G_CALLBACK (cv_tree_activated_cb), NULL);
g_signal_connect (G_OBJECT (view), "scroll-event", g_signal_connect (G_OBJECT (view), "scroll_event",
G_CALLBACK (cv_tree_scroll_event_cb), NULL); G_CALLBACK (cv_tree_scroll_event_cb), NULL);
gtk_drag_dest_set (view, GTK_DEST_DEFAULT_ALL, dnd_dest_target, 1, gtk_drag_dest_set (view, GTK_DEST_DEFAULT_ALL, dnd_dest_target, 1,
GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
gtk_drag_source_set (view, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_COPY); gtk_drag_source_set (view, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_COPY);
g_signal_connect (G_OBJECT (view), "drag-begin", g_signal_connect (G_OBJECT (view), "drag_begin",
G_CALLBACK (mg_drag_begin_cb), NULL); G_CALLBACK (mg_drag_begin_cb), NULL);
g_signal_connect (G_OBJECT (view), "drag-drop", g_signal_connect (G_OBJECT (view), "drag_drop",
G_CALLBACK (mg_drag_drop_cb), NULL); G_CALLBACK (mg_drag_drop_cb), NULL);
g_signal_connect (G_OBJECT (view), "drag-motion", g_signal_connect (G_OBJECT (view), "drag_motion",
G_CALLBACK (mg_drag_motion_cb), NULL); G_CALLBACK (mg_drag_motion_cb), NULL);
g_signal_connect (G_OBJECT (view), "drag-end", g_signal_connect (G_OBJECT (view), "drag_end",
G_CALLBACK (mg_drag_end_cb), NULL); G_CALLBACK (mg_drag_end_cb), NULL);
((treeview *)cv)->tree = GTK_TREE_VIEW (view); ((treeview *)cv)->tree = GTK_TREE_VIEW (view);

View File

@@ -863,7 +863,7 @@ fe_dcc_open_recv_win (int passive)
gtk_tree_selection_set_mode (dccfwin.sel, GTK_SELECTION_MULTIPLE); gtk_tree_selection_set_mode (dccfwin.sel, GTK_SELECTION_MULTIPLE);
if (!prefs.hex_gui_tab_utils) if (!prefs.hex_gui_tab_utils)
g_signal_connect (G_OBJECT (dccfwin.window), "configure-event", g_signal_connect (G_OBJECT (dccfwin.window), "configure_event",
G_CALLBACK (dcc_configure_cb), 0); G_CALLBACK (dcc_configure_cb), 0);
g_signal_connect (G_OBJECT (dccfwin.sel), "changed", g_signal_connect (G_OBJECT (dccfwin.sel), "changed",
G_CALLBACK (dcc_row_cb), NULL); G_CALLBACK (dcc_row_cb), NULL);

View File

@@ -290,7 +290,7 @@ editlist_treeview_new (GtkWidget *box, char *title1, char *title2)
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE); gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE); gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE);
g_signal_connect (G_OBJECT (view), "key-press-event", g_signal_connect (G_OBJECT (view), "key_press_event",
G_CALLBACK (editlist_keypress), NULL); G_CALLBACK (editlist_keypress), NULL);
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL); gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);

View File

@@ -59,7 +59,6 @@
#include "plugin-notification.h" #include "plugin-notification.h"
#include "theme/theme-manager.h" #include "theme/theme-manager.h"
#include "theme/theme-application.h" #include "theme/theme-application.h"
#include "preferences-persistence.h"
#ifdef USE_LIBCANBERRA #ifdef USE_LIBCANBERRA
#include <canberra.h> #include <canberra.h>
@@ -586,21 +585,6 @@ fe_cleanup (void)
{ {
} }
fe_preferences_save_result
fe_preferences_persistence_save_all (void)
{
PreferencesPersistenceResult save_result;
fe_preferences_save_result result;
save_result = preferences_persistence_save_all ();
result.success = save_result.success;
result.partial_failure = save_result.partial_failure;
result.config_failed = save_result.config_failed;
result.theme_failed = save_result.theme_failed;
return result;
}
void void
fe_exit (void) fe_exit (void)
{ {
@@ -774,15 +758,11 @@ fe_set_topic (session *sess, char *topic, char *stripped_topic)
{ {
if (prefs.hex_text_stripcolor_topic) if (prefs.hex_text_stripcolor_topic)
{ {
gtk_text_buffer_set_text ( gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), stripped_topic);
gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry)),
stripped_topic, -1);
} }
else else
{ {
gtk_text_buffer_set_text ( gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), topic);
gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry)),
topic, -1);
} }
mg_set_topic_tip (sess); mg_set_topic_tip (sess);
} }
@@ -1355,79 +1335,22 @@ fe_open_url_inner (const char *url)
g_free (escaped_url); g_free (escaped_url);
} }
static gboolean
fe_open_url_is_local_path (const char *url)
{
if (g_path_is_absolute (url) || g_file_test (url, G_FILE_TEST_EXISTS))
return TRUE;
#ifdef WIN32
if (g_ascii_isalpha (url[0]) && url[1] == ':' &&
(url[2] == '\\' || url[2] == '/'))
return TRUE;
if (url[0] == '\\' && url[1] == '\\')
return TRUE;
#endif
return FALSE;
}
static char *
fe_open_url_canonicalize_path (const char *path)
{
char *absolute_path;
char *cwd;
if (!path || path[0] == '\0')
return NULL;
if (g_path_is_absolute (path))
return g_strdup (path);
cwd = g_get_current_dir ();
absolute_path = g_build_filename (cwd, path, NULL);
g_free (cwd);
return absolute_path;
}
void void
fe_open_url (const char *url) fe_open_url (const char *url)
{ {
int url_type = url_check_word (url); int url_type = url_check_word (url);
char *uri; char *uri;
char *path;
char *path_uri;
if (fe_open_url_is_local_path (url))
{
path = fe_open_url_canonicalize_path (url);
path_uri = g_filename_to_uri (path, NULL, NULL);
g_free (path);
if (path_uri)
{
fe_open_url_inner (path_uri);
g_free (path_uri);
return;
}
}
/* gvfs likes file:// */ /* gvfs likes file:// */
if (url_type == WORD_PATH) if (url_type == WORD_PATH)
{ {
path = fe_open_url_canonicalize_path (url); #ifndef WIN32
path_uri = g_filename_to_uri (path, NULL, NULL); uri = g_strconcat ("file://", url, NULL);
g_free (path); fe_open_url_inner (uri);
if (path_uri) g_free (uri);
{ #else
fe_open_url_inner (path_uri);
g_free (path_uri);
}
else
{
fe_open_url_inner (url); fe_open_url_inner (url);
} #endif
} }
/* IPv6 addr. Add http:// */ /* IPv6 addr. Add http:// */
else if (url_type == WORD_HOST6) else if (url_type == WORD_HOST6)

View File

@@ -61,7 +61,6 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
<ClInclude Include="icon-resolver.h" /> <ClInclude Include="icon-resolver.h" />
<ClInclude Include="joind.h" /> <ClInclude Include="joind.h" />
<ClInclude Include="maingui.h" /> <ClInclude Include="maingui.h" />
<ClInclude Include="preferences-persistence.h" />
<ClInclude Include="menu.h" /> <ClInclude Include="menu.h" />
<ClInclude Include="notifications\notification-backend.h" /> <ClInclude Include="notifications\notification-backend.h" />
<ClInclude Include="notifygui.h" /> <ClInclude Include="notifygui.h" />
@@ -108,7 +107,6 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
<ClCompile Include="notifications\notification-windows.c" /> <ClCompile Include="notifications\notification-windows.c" />
<ClCompile Include="notifygui.c" /> <ClCompile Include="notifygui.c" />
<ClCompile Include="pixmaps.c" /> <ClCompile Include="pixmaps.c" />
<ClCompile Include="preferences-persistence.c" />
<ClCompile Include="plugin-notification.c" /> <ClCompile Include="plugin-notification.c" />
<ClCompile Include="plugin-tray.c" /> <ClCompile Include="plugin-tray.c" />
<ClCompile Include="plugingui.c" /> <ClCompile Include="plugingui.c" />

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">
@@ -51,9 +51,6 @@
<ClInclude Include="maingui.h"> <ClInclude Include="maingui.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="preferences-persistence.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="menu.h"> <ClInclude Include="menu.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@@ -185,9 +182,6 @@
<ClCompile Include="pixmaps.c"> <ClCompile Include="pixmaps.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="preferences-persistence.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="plugingui.c"> <ClCompile Include="plugingui.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@@ -470,7 +470,7 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess)
return 1; return 1;
case 2: case 2:
g_signal_stop_emission_by_name (G_OBJECT (wid), g_signal_stop_emission_by_name (G_OBJECT (wid),
"key-press-event"); "key_press_event");
return 1; return 1;
} }
} }

View File

@@ -662,7 +662,7 @@ gtkutil_esc_destroy (GtkWidget * win, GdkEventKey * key, gpointer userdata)
void void
gtkutil_destroy_on_esc (GtkWidget *win) gtkutil_destroy_on_esc (GtkWidget *win)
{ {
g_signal_connect (G_OBJECT (win), "key-press-event", G_CALLBACK (gtkutil_esc_destroy), win); g_signal_connect (G_OBJECT (win), "key_press_event", G_CALLBACK (gtkutil_esc_destroy), win);
} }
void void

View File

@@ -241,7 +241,7 @@ joind_show_dialog (server *serv)
g_signal_connect (G_OBJECT (dialog1), "destroy", g_signal_connect (G_OBJECT (dialog1), "destroy",
G_CALLBACK (joind_destroy_cb), serv); G_CALLBACK (joind_destroy_cb), serv);
g_signal_connect (G_OBJECT (entry1), "focus-in-event", g_signal_connect (G_OBJECT (entry1), "focus_in_event",
G_CALLBACK (joind_entryfocus_cb), serv); G_CALLBACK (joind_entryfocus_cb), serv);
g_signal_connect (G_OBJECT (entry1), "activate", g_signal_connect (G_OBJECT (entry1), "activate",
G_CALLBACK (joind_entryenter_cb), okbutton1); G_CALLBACK (joind_entryenter_cb), okbutton1);

View File

@@ -52,7 +52,6 @@
#include "theme/theme-palette.h" #include "theme/theme-palette.h"
#include "maingui.h" #include "maingui.h"
#include "menu.h" #include "menu.h"
#include "preferences-persistence.h"
#include "fkeys.h" #include "fkeys.h"
#include "userlistgui.h" #include "userlistgui.h"
#include "chanview.h" #include "chanview.h"
@@ -174,81 +173,6 @@ enum
static void mg_apply_emoji_fallback_widget (GtkWidget *widget); static void mg_apply_emoji_fallback_widget (GtkWidget *widget);
#define MG_CONFIG_SAVE_DEBOUNCE_MS 250
static guint mg_config_save_source_id = 0;
static gboolean mg_config_prefs_dirty = FALSE;
static void
mg_show_save_failure (const PreferencesPersistenceResult *save_result)
{
char buffer[192];
if (!save_result || save_result->success)
return;
if (save_result->partial_failure)
{
fe_message (_("Could not fully save preferences. zoitechat.conf was written, but colors.conf failed. Retry is possible."), FE_MSG_ERROR);
return;
}
g_snprintf (buffer, sizeof (buffer), _("Could not save preferences (%s). Retry is possible."), save_result->failed_file ? save_result->failed_file : _("unknown file"));
fe_message (buffer, FE_MSG_ERROR);
}
static gboolean
mg_config_save_timeout_cb (gpointer userdata)
{
PreferencesPersistenceResult save_result;
mg_config_save_source_id = 0;
if (!mg_config_prefs_dirty)
return G_SOURCE_REMOVE;
save_result = preferences_persistence_save_all ();
if (!save_result.success)
mg_show_save_failure (&save_result);
mg_config_prefs_dirty = FALSE;
return G_SOURCE_REMOVE;
}
static void
mg_schedule_config_save (void)
{
if (!mg_config_prefs_dirty)
return;
if (mg_config_save_source_id != 0)
g_source_remove (mg_config_save_source_id);
mg_config_save_source_id = g_timeout_add (MG_CONFIG_SAVE_DEBOUNCE_MS,
mg_config_save_timeout_cb,
NULL);
}
static void
mg_flush_config_save (void)
{
PreferencesPersistenceResult save_result;
if (mg_config_save_source_id != 0)
{
g_source_remove (mg_config_save_source_id);
mg_config_save_source_id = 0;
}
if (mg_config_prefs_dirty)
{
save_result = preferences_persistence_save_all ();
if (!save_result.success)
mg_show_save_failure (&save_result);
mg_config_prefs_dirty = FALSE;
}
}
static inline void static inline void
mg_set_source_color (cairo_t *cr, const XTextColor *color) mg_set_source_color (cairo_t *cr, const XTextColor *color)
{ {
@@ -746,7 +670,7 @@ mg_spellcheck_cb (SexySpellEntry *entry, gchar *word, gpointer data)
{ {
/* This can cause freezes on long words, nicks arn't very long anyway. */ /* This can cause freezes on long words, nicks arn't very long anyway. */
if (strlen (word) > 20) if (strlen (word) > 20)
return FALSE; return TRUE;
/* Ignore anything we think is a valid url */ /* Ignore anything we think is a valid url */
if (url_check_word (word) != 0) if (url_check_word (word) != 0)
@@ -837,10 +761,6 @@ fe_set_title (session *sess)
static gboolean static gboolean
mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata) mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata)
{ {
guint win_state;
guint win_fullscreen;
gboolean changed = FALSE;
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) && if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) && (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray && prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
@@ -849,31 +769,13 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
tray_toggle_visibility (TRUE); tray_toggle_visibility (TRUE);
} }
win_state = 0; prefs.hex_gui_win_state = 0;
if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
win_state = 1; prefs.hex_gui_win_state = 1;
win_fullscreen = 0; prefs.hex_gui_win_fullscreen = 0;
if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
win_fullscreen = 1; prefs.hex_gui_win_fullscreen = 1;
if (prefs.hex_gui_win_state != win_state)
{
prefs.hex_gui_win_state = win_state;
changed = TRUE;
}
if (prefs.hex_gui_win_fullscreen != win_fullscreen)
{
prefs.hex_gui_win_fullscreen = win_fullscreen;
changed = TRUE;
}
if (changed)
{
mg_config_prefs_dirty = TRUE;
mg_schedule_config_save ();
}
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen); menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
@@ -887,87 +789,30 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
static gboolean static gboolean
mg_configure_cb (GtkWidget *wid, GdkEventConfigure *event, session *sess) mg_configure_cb (GtkWidget *wid, GdkEventConfigure *event, session *sess)
{ {
gboolean changed = FALSE; if (sess == NULL) /* for the main_window */
if (sess == NULL)
{ {
if (mg_gui) if (mg_gui)
{ {
if (prefs.hex_gui_win_save && !prefs.hex_gui_win_state && !prefs.hex_gui_win_fullscreen) if (prefs.hex_gui_win_save && !prefs.hex_gui_win_state && !prefs.hex_gui_win_fullscreen)
{ {
int win_left; sess = current_sess;
int win_top; gtk_window_get_position (GTK_WINDOW (wid), &prefs.hex_gui_win_left,
int win_width; &prefs.hex_gui_win_top);
int win_height; gtk_window_get_size (GTK_WINDOW (wid), &prefs.hex_gui_win_width,
&prefs.hex_gui_win_height);
}
}
}
gtk_window_get_position (GTK_WINDOW (wid), &win_left, &win_top); if (sess)
gtk_window_get_size (GTK_WINDOW (wid), &win_width, &win_height);
if (prefs.hex_gui_win_left != win_left)
{ {
prefs.hex_gui_win_left = win_left; if (sess->type == SESS_DIALOG && prefs.hex_gui_win_save)
changed = TRUE;
}
if (prefs.hex_gui_win_top != win_top)
{ {
prefs.hex_gui_win_top = win_top; gtk_window_get_position (GTK_WINDOW (wid), &prefs.hex_gui_dialog_left,
changed = TRUE; &prefs.hex_gui_dialog_top);
gtk_window_get_size (GTK_WINDOW (wid), &prefs.hex_gui_dialog_width,
&prefs.hex_gui_dialog_height);
} }
if (prefs.hex_gui_win_width != win_width)
{
prefs.hex_gui_win_width = win_width;
changed = TRUE;
}
if (prefs.hex_gui_win_height != win_height)
{
prefs.hex_gui_win_height = win_height;
changed = TRUE;
}
}
}
}
else if (sess->type == SESS_DIALOG && prefs.hex_gui_win_save)
{
int dialog_left;
int dialog_top;
int dialog_width;
int dialog_height;
gtk_window_get_position (GTK_WINDOW (wid), &dialog_left, &dialog_top);
gtk_window_get_size (GTK_WINDOW (wid), &dialog_width, &dialog_height);
if (prefs.hex_gui_dialog_left != dialog_left)
{
prefs.hex_gui_dialog_left = dialog_left;
changed = TRUE;
}
if (prefs.hex_gui_dialog_top != dialog_top)
{
prefs.hex_gui_dialog_top = dialog_top;
changed = TRUE;
}
if (prefs.hex_gui_dialog_width != dialog_width)
{
prefs.hex_gui_dialog_width = dialog_width;
changed = TRUE;
}
if (prefs.hex_gui_dialog_height != dialog_height)
{
prefs.hex_gui_dialog_height = dialog_height;
changed = TRUE;
}
}
if (changed)
{
mg_config_prefs_dirty = TRUE;
mg_schedule_config_save ();
} }
return FALSE; return FALSE;
@@ -1075,18 +920,13 @@ mg_unpopulate (session *sess)
{ {
restore_gui *res; restore_gui *res;
session_gui *gui; session_gui *gui;
GtkTextBuffer *topic_buffer;
GtkTextIter start;
GtkTextIter end;
int i; int i;
gui = sess->gui; gui = sess->gui;
res = sess->res; res = sess->res;
res->input_text = g_strdup (SPELL_ENTRY_GET_TEXT (gui->input_box)); res->input_text = g_strdup (SPELL_ENTRY_GET_TEXT (gui->input_box));
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry)); res->topic_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->topic_entry)));
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
res->topic_text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
res->limit_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry))); res->limit_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry)));
res->key_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry))); res->key_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry)));
if (gui->laginfo) if (gui->laginfo)
@@ -1163,9 +1003,6 @@ void
mg_set_topic_tip (session *sess) mg_set_topic_tip (session *sess)
{ {
char *text; char *text;
GtkTextBuffer *topic_buffer;
GtkTextIter start;
GtkTextIter end;
switch (sess->type) switch (sess->type)
{ {
@@ -1180,14 +1017,11 @@ mg_set_topic_tip (session *sess)
gtk_widget_set_tooltip_text (sess->gui->topic_entry, _("No topic is set")); gtk_widget_set_tooltip_text (sess->gui->topic_entry, _("No topic is set"));
break; break;
default: default:
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry)); if (gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry)) &&
gtk_text_buffer_get_bounds (topic_buffer, &start, &end); gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry))[0])
text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE); gtk_widget_set_tooltip_text (sess->gui->topic_entry, (char *)gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry)));
if (text[0])
gtk_widget_set_tooltip_text (sess->gui->topic_entry, text);
else else
gtk_widget_set_tooltip_text (sess->gui->topic_entry, NULL); gtk_widget_set_tooltip_text (sess->gui->topic_entry, NULL);
g_free (text);
} }
} }
@@ -1218,14 +1052,9 @@ mg_userlist_showhide (session *sess, int show)
session_gui *gui = sess->gui; session_gui *gui = sess->gui;
int handle_size; int handle_size;
int right_size; int right_size;
int min_right_size;
GtkAllocation allocation; GtkAllocation allocation;
gtk_widget_get_size_request (gui->user_box, &min_right_size, NULL); right_size = MAX (prefs.hex_gui_pane_right_size, prefs.hex_gui_pane_right_size_min);
if (min_right_size < 1)
min_right_size = 1;
right_size = MAX (prefs.hex_gui_pane_right_size, min_right_size);
if (show) if (show)
{ {
@@ -1335,7 +1164,7 @@ mg_populate (session *sess)
/* hide the userlist */ /* hide the userlist */
mg_decide_userlist (sess, FALSE); mg_decide_userlist (sess, FALSE);
/* shouldn't edit the topic */ /* shouldn't edit the topic */
gtk_text_view_set_editable (GTK_TEXT_VIEW (gui->topic_entry), FALSE); gtk_editable_set_editable (GTK_EDITABLE (gui->topic_entry), FALSE);
/* might be hidden from server tab */ /* might be hidden from server tab */
if (prefs.hex_gui_topicbar) if (prefs.hex_gui_topicbar)
gtk_widget_show (gui->topic_bar); gtk_widget_show (gui->topic_bar);
@@ -1357,8 +1186,8 @@ mg_populate (session *sess)
gtk_widget_show (gui->topicbutton_box); gtk_widget_show (gui->topicbutton_box);
/* show the userlist */ /* show the userlist */
mg_decide_userlist (sess, FALSE); mg_decide_userlist (sess, FALSE);
/* let the topic be edited */ /* let the topic be editted */
gtk_text_view_set_editable (GTK_TEXT_VIEW (gui->topic_entry), TRUE); gtk_editable_set_editable (GTK_EDITABLE (gui->topic_entry), TRUE);
if (prefs.hex_gui_topicbar) if (prefs.hex_gui_topicbar)
gtk_widget_show (gui->topic_bar); gtk_widget_show (gui->topic_bar);
} }
@@ -1378,21 +1207,8 @@ mg_populate (session *sess)
if (gui->is_tab) if (gui->is_tab)
gtk_widget_set_sensitive (gui->menu, TRUE); gtk_widget_set_sensitive (gui->menu, TRUE);
if (res->topic_text) /* restore all the GtkEntry's */
{ mg_restore_entry (gui->topic_entry, &res->topic_text);
GtkTextBuffer *topic_buffer;
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry));
gtk_text_buffer_set_text (topic_buffer, res->topic_text, -1);
g_free (res->topic_text);
res->topic_text = NULL;
} else
{
GtkTextBuffer *topic_buffer;
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry));
gtk_text_buffer_set_text (topic_buffer, "", -1);
}
mg_restore_speller (gui->input_box, &res->input_text); mg_restore_speller (gui->input_box, &res->input_text);
mg_restore_entry (gui->key_entry, &res->key_text); mg_restore_entry (gui->key_entry, &res->key_text);
mg_restore_entry (gui->limit_entry, &res->limit_text); mg_restore_entry (gui->limit_entry, &res->limit_text);
@@ -2298,204 +2114,30 @@ mg_create_userlistbuttons (GtkWidget *box)
} }
static void static void
mg_topic_cb (GtkWidget *entry) mg_topic_cb (GtkWidget *entry, gpointer userdata)
{ {
session *sess = current_sess; session *sess = current_sess;
GtkTextBuffer *topic_buffer;
GtkTextIter start;
GtkTextIter end;
char *text; char *text;
if (sess->channel[0] && sess->server->connected && sess->type == SESS_CHANNEL) if (sess->channel[0] && sess->server->connected && sess->type == SESS_CHANNEL)
{ {
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry)); text = (char *)gtk_entry_get_text (GTK_ENTRY (entry));
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
if (text[0] == 0) if (text[0] == 0)
sess->server->p_topic (sess->server, sess->channel, NULL); text = NULL;
else
sess->server->p_topic (sess->server, sess->channel, text); sess->server->p_topic (sess->server, sess->channel, text);
g_free (text);
} else } else
{ gtk_entry_set_text (GTK_ENTRY (entry), "");
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
gtk_text_buffer_set_text (topic_buffer, "", -1);
}
/* restore focus to the input widget, where the next input will most /* restore focus to the input widget, where the next input will most
likely be */ likely be */
gtk_widget_grab_focus (sess->gui->input_box); gtk_widget_grab_focus (sess->gui->input_box);
} }
static gboolean
mg_topic_key_press_cb (GtkWidget *entry, GdkEventKey *event, gpointer userdata)
{
if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter)
{
mg_topic_cb (entry);
return TRUE;
}
return FALSE;
}
static char *
mg_topic_get_word_at_pos (GtkWidget *entry, gdouble event_x, gdouble event_y, int *word_pos)
{
GtkTextBuffer *buffer;
GtkTextIter iter;
GtkTextIter start;
GtkTextIter end;
GtkTextIter cursor;
int x;
int y;
x = (int)event_x;
y = (int)event_y;
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (entry), GTK_TEXT_WINDOW_TEXT,
x, y, &x, &y);
gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (entry), &iter, x, y);
cursor = iter;
start = iter;
while (!gtk_text_iter_starts_line (&start))
{
GtkTextIter prev = start;
gunichar ch;
gtk_text_iter_backward_char (&prev);
ch = gtk_text_iter_get_char (&prev);
if (g_unichar_isspace (ch))
break;
start = prev;
}
end = iter;
while (!gtk_text_iter_ends_line (&end))
{
gunichar ch;
ch = gtk_text_iter_get_char (&end);
if (ch == 0 || g_unichar_isspace (ch))
break;
gtk_text_iter_forward_char (&end);
}
if (gtk_text_iter_equal (&start, &end))
return NULL;
if (word_pos)
{
char *prefix;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
prefix = gtk_text_buffer_get_text (buffer, &start, &cursor, FALSE);
*word_pos = (int)strlen (prefix);
g_free (prefix);
}
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
}
static void
mg_topic_set_cursor (GtkWidget *entry, GdkCursorType cursor_type)
{
GdkWindow *text_window;
GdkDisplay *display;
GdkCursor *cursor;
text_window = gtk_text_view_get_window (GTK_TEXT_VIEW (entry), GTK_TEXT_WINDOW_TEXT);
if (!text_window)
return;
display = gdk_window_get_display (text_window);
cursor = gdk_cursor_new_for_display (display, cursor_type);
gdk_window_set_cursor (text_window, cursor);
g_object_unref (cursor);
}
static gboolean
mg_topic_word_is_clickable (const char *word, int word_pos)
{
int start;
int end;
if (!word || word[0] == 0)
return FALSE;
if (strcmp (word, "/") == 0)
return FALSE;
if (url_check_word (word) == 0)
return FALSE;
url_last (&start, &end);
return word_pos >= start && word_pos < end;
}
static gboolean
mg_topic_motion_cb (GtkWidget *entry, GdkEventMotion *event, gpointer userdata)
{
char *word;
int word_pos;
gboolean word_is_clickable;
word_pos = 0;
word = mg_topic_get_word_at_pos (entry, event->x, event->y, &word_pos);
word_is_clickable = mg_topic_word_is_clickable (word, word_pos);
if (word_is_clickable)
mg_topic_set_cursor (entry, GDK_HAND2);
else
mg_topic_set_cursor (entry, GDK_XTERM);
g_free (word);
return FALSE;
}
static gboolean
mg_topic_leave_cb (GtkWidget *entry, GdkEventCrossing *event, gpointer userdata)
{
mg_topic_set_cursor (entry, GDK_XTERM);
return FALSE;
}
static gboolean
mg_topic_button_release_cb (GtkWidget *entry, GdkEventButton *event, gpointer userdata)
{
char *word;
int word_pos;
int start;
int end;
if (event->button != 1)
return FALSE;
word_pos = 0;
word = mg_topic_get_word_at_pos (entry, event->x, event->y, &word_pos);
if (!word)
return FALSE;
if (mg_topic_word_is_clickable (word, word_pos))
{
url_last (&start, &end);
word[end] = 0;
fe_open_url (word + start);
g_free (word);
return TRUE;
}
g_free (word);
return FALSE;
}
static void static void
mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata) mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata)
{ {
GSList *list, *next; GSList *list, *next;
session *sess; session *sess;
mg_flush_config_save ();
zoitechat_is_quitting = TRUE; zoitechat_is_quitting = TRUE;
/* see if there's any non-tab windows left */ /* see if there's any non-tab windows left */
@@ -2773,20 +2415,6 @@ mg_apply_entry_style (GtkWidget *entry)
theme_manager_apply_entry_palette (entry, input_style->font_desc); theme_manager_apply_entry_palette (entry, input_style->font_desc);
} }
static gboolean
mg_entry_select_all (GtkWidget *entry, GdkEventKey *event, gpointer userdata)
{
if ((event->state & GDK_CONTROL_MASK) &&
!(event->state & (GDK_SHIFT_MASK | GDK_MOD1_MASK | GDK_META_MASK)) &&
(event->keyval == GDK_KEY_a || event->keyval == GDK_KEY_A))
{
gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
return TRUE;
}
return FALSE;
}
static void static void
mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box) mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
{ {
@@ -2806,8 +2434,6 @@ mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
mg_apply_emoji_fallback_widget (gui->key_entry); mg_apply_emoji_fallback_widget (gui->key_entry);
g_signal_connect (G_OBJECT (gui->key_entry), "activate", g_signal_connect (G_OBJECT (gui->key_entry), "activate",
G_CALLBACK (mg_key_entry_cb), NULL); G_CALLBACK (mg_key_entry_cb), NULL);
g_signal_connect (G_OBJECT (gui->key_entry), "key-press-event",
G_CALLBACK (mg_entry_select_all), NULL);
if (prefs.hex_gui_input_style) if (prefs.hex_gui_input_style)
mg_apply_entry_style (gui->key_entry); mg_apply_entry_style (gui->key_entry);
@@ -2821,8 +2447,6 @@ mg_create_chanmodebuttons (session_gui *gui, GtkWidget *box)
mg_apply_emoji_fallback_widget (gui->limit_entry); mg_apply_emoji_fallback_widget (gui->limit_entry);
g_signal_connect (G_OBJECT (gui->limit_entry), "activate", g_signal_connect (G_OBJECT (gui->limit_entry), "activate",
G_CALLBACK (mg_limit_entry_cb), NULL); G_CALLBACK (mg_limit_entry_cb), NULL);
g_signal_connect (G_OBJECT (gui->limit_entry), "key-press-event",
G_CALLBACK (mg_entry_select_all), NULL);
if (prefs.hex_gui_input_style) if (prefs.hex_gui_input_style)
mg_apply_entry_style (gui->limit_entry); mg_apply_entry_style (gui->limit_entry);
@@ -2846,18 +2470,12 @@ mg_dialog_button_cb (GtkWidget *wid, char *cmd)
char buf[128]; char buf[128];
char *host = ""; char *host = "";
char *topic; char *topic;
char *topic_text;
GtkTextBuffer *topic_buffer;
GtkTextIter start;
GtkTextIter end;
if (!current_sess) if (!current_sess)
return; return;
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (current_sess->gui->topic_entry)); topic = (char *)(gtk_entry_get_text (GTK_ENTRY (current_sess->gui->topic_entry)));
gtk_text_buffer_get_bounds (topic_buffer, &start, &end); topic = strrchr (topic, '@');
topic_text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
topic = strrchr (topic_text, '@');
if (topic) if (topic)
host = topic + 1; host = topic + 1;
@@ -2866,7 +2484,6 @@ mg_dialog_button_cb (GtkWidget *wid, char *cmd)
current_sess->channel, ""); current_sess->channel, "");
handle_command (current_sess, buf, TRUE); handle_command (current_sess, buf, TRUE);
g_free (topic_text);
/* dirty trick to avoid auto-selection */ /* dirty trick to avoid auto-selection */
SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, FALSE); SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, FALSE);
@@ -2913,23 +2530,16 @@ mg_create_topicbar (session *sess, GtkWidget *box)
if (!gui->is_tab) if (!gui->is_tab)
sess->res->tab = NULL; sess->res->tab = NULL;
gui->topic_entry = topic = gtk_text_view_new (); gui->topic_entry = topic = sexy_spell_entry_new ();
gtk_widget_set_name (topic, "zoitechat-inputbox"); gtk_widget_set_name (topic, "zoitechat-inputbox");
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (topic), GTK_WRAP_WORD_CHAR); sexy_spell_entry_set_checked (SEXY_SPELL_ENTRY (topic), FALSE);
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (topic), 4);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (topic), 4);
gtk_box_pack_start (GTK_BOX (hbox), topic, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), topic, TRUE, TRUE, 0);
mg_apply_emoji_fallback_widget (topic); mg_apply_emoji_fallback_widget (topic);
gtk_widget_add_events (topic, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | g_signal_connect (G_OBJECT (topic), "activate",
GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); G_CALLBACK (mg_topic_cb), 0);
g_signal_connect (G_OBJECT (topic), "key-press-event",
G_CALLBACK (mg_topic_key_press_cb), NULL); if (prefs.hex_gui_input_style)
g_signal_connect (G_OBJECT (topic), "button-release-event", mg_apply_entry_style (topic);
G_CALLBACK (mg_topic_button_release_cb), NULL);
g_signal_connect (G_OBJECT (topic), "motion-notify-event",
G_CALLBACK (mg_topic_motion_cb), NULL);
g_signal_connect (G_OBJECT (topic), "leave-notify-event",
G_CALLBACK (mg_topic_leave_cb), NULL);
gui->topicbutton_box = bbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0); gui->topicbutton_box = bbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), bbox, 0, 0, 0); gtk_box_pack_start (GTK_BOX (hbox), bbox, 0, 0, 0);
@@ -3113,18 +2723,18 @@ mg_create_textarea (session *sess, GtkWidget *box)
gtk_drag_dest_set (gui->vscrollbar, 5, dnd_dest_targets, 2, gtk_drag_dest_set (gui->vscrollbar, 5, dnd_dest_targets, 2,
GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
g_signal_connect (G_OBJECT (gui->vscrollbar), "drag-begin", g_signal_connect (G_OBJECT (gui->vscrollbar), "drag_begin",
G_CALLBACK (mg_drag_begin_cb), NULL); G_CALLBACK (mg_drag_begin_cb), NULL);
g_signal_connect (G_OBJECT (gui->vscrollbar), "drag-drop", g_signal_connect (G_OBJECT (gui->vscrollbar), "drag_drop",
G_CALLBACK (mg_drag_drop_cb), NULL); G_CALLBACK (mg_drag_drop_cb), NULL);
g_signal_connect (G_OBJECT (gui->vscrollbar), "drag-motion", g_signal_connect (G_OBJECT (gui->vscrollbar), "drag_motion",
G_CALLBACK (mg_drag_motion_cb), gui->vscrollbar); G_CALLBACK (mg_drag_motion_cb), gui->vscrollbar);
g_signal_connect (G_OBJECT (gui->vscrollbar), "drag-end", g_signal_connect (G_OBJECT (gui->vscrollbar), "drag_end",
G_CALLBACK (mg_drag_end_cb), NULL); G_CALLBACK (mg_drag_end_cb), NULL);
gtk_drag_dest_set (gui->xtext, GTK_DEST_DEFAULT_ALL, dnd_targets, 1, gtk_drag_dest_set (gui->xtext, GTK_DEST_DEFAULT_ALL, dnd_targets, 1,
GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
g_signal_connect (G_OBJECT (gui->xtext), "drag-data-received", g_signal_connect (G_OBJECT (gui->xtext), "drag_data_received",
G_CALLBACK (mg_dialog_dnd_drop), NULL); G_CALLBACK (mg_dialog_dnd_drop), NULL);
} }
@@ -3300,8 +2910,6 @@ mg_create_userlist (session_gui *gui, GtkWidget *box)
gtk_box_pack_start (GTK_BOX (vbox), frame, 0, 0, GUI_SPACING); gtk_box_pack_start (GTK_BOX (vbox), frame, 0, 0, GUI_SPACING);
gui->namelistinfo = gtk_label_new (NULL); gui->namelistinfo = gtk_label_new (NULL);
gtk_label_set_xalign (GTK_LABEL (gui->namelistinfo), 0.0f);
gtk_widget_set_halign (gui->namelistinfo, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (frame), gui->namelistinfo); gtk_container_add (GTK_CONTAINER (frame), gui->namelistinfo);
gui->user_tree = ulist = userlist_create (vbox); gui->user_tree = ulist = userlist_create (vbox);
@@ -3376,12 +2984,12 @@ mg_create_center (session *sess, session_gui *gui, GtkWidget *box)
if (prefs.hex_gui_win_swap) if (prefs.hex_gui_win_swap)
{ {
gtk_paned_pack2 (GTK_PANED (gui->hpane_left), gui->vpane_left, FALSE, FALSE); gtk_paned_pack2 (GTK_PANED (gui->hpane_left), gui->vpane_left, FALSE, TRUE);
gtk_paned_pack1 (GTK_PANED (gui->hpane_left), gui->hpane_right, TRUE, TRUE); gtk_paned_pack1 (GTK_PANED (gui->hpane_left), gui->hpane_right, TRUE, TRUE);
} }
else else
{ {
gtk_paned_pack1 (GTK_PANED (gui->hpane_left), gui->vpane_left, FALSE, FALSE); gtk_paned_pack1 (GTK_PANED (gui->hpane_left), gui->vpane_left, FALSE, TRUE);
gtk_paned_pack2 (GTK_PANED (gui->hpane_left), gui->hpane_right, TRUE, TRUE); gtk_paned_pack2 (GTK_PANED (gui->hpane_left), gui->hpane_right, TRUE, TRUE);
} }
gtk_paned_pack2 (GTK_PANED (gui->hpane_right), gui->vpane_right, FALSE, TRUE); gtk_paned_pack2 (GTK_PANED (gui->hpane_right), gui->vpane_right, FALSE, TRUE);
@@ -3840,8 +3448,7 @@ static void
search_set_option (GtkToggleButton *but, guint *pref) search_set_option (GtkToggleButton *but, guint *pref)
{ {
*pref = gtk_toggle_button_get_active(but); *pref = gtk_toggle_button_get_active(but);
if (!save_config ()) save_config();
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
} }
void void
@@ -3897,7 +3504,7 @@ mg_create_search(session *sess, GtkWidget *box)
gtk_widget_set_size_request (gui->shentry, 180, -1); gtk_widget_set_size_request (gui->shentry, 180, -1);
mg_apply_emoji_fallback_widget (entry); mg_apply_emoji_fallback_widget (entry);
gui->search_changed_signal = g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(search_handle_change), sess); gui->search_changed_signal = g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(search_handle_change), sess);
g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK (search_handle_esc), sess); g_signal_connect (G_OBJECT (entry), "key_press_event", G_CALLBACK (search_handle_esc), sess);
g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(mg_search_handle_next), sess); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(mg_search_handle_next), sess);
gtk_entry_set_icon_activatable (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, FALSE); gtk_entry_set_icon_activatable (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, FALSE);
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("Search hit end or not found.")); gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("Search hit end or not found."));
@@ -3979,11 +3586,11 @@ mg_create_entry (session *sess, GtkWidget *box)
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
gtk_widget_set_name (entry, "zoitechat-inputbox"); gtk_widget_set_name (entry, "zoitechat-inputbox");
g_signal_connect (G_OBJECT (entry), "key-press-event", g_signal_connect (G_OBJECT (entry), "key_press_event",
G_CALLBACK (key_handle_key_press), NULL); G_CALLBACK (key_handle_key_press), NULL);
g_signal_connect (G_OBJECT (entry), "focus-in-event", g_signal_connect (G_OBJECT (entry), "focus_in_event",
G_CALLBACK (mg_inputbox_focus), gui); G_CALLBACK (mg_inputbox_focus), gui);
g_signal_connect (G_OBJECT (entry), "populate-popup", g_signal_connect (G_OBJECT (entry), "populate_popup",
G_CALLBACK (mg_inputbox_rightclick), NULL); G_CALLBACK (mg_inputbox_rightclick), NULL);
g_signal_connect (G_OBJECT (entry), "word-check", g_signal_connect (G_OBJECT (entry), "word-check",
G_CALLBACK (mg_spellcheck_cb), NULL); G_CALLBACK (mg_spellcheck_cb), NULL);
@@ -4146,11 +3753,11 @@ mg_create_topwindow (session *sess)
gtk_container_set_border_width (GTK_CONTAINER (win), GUI_BORDER); gtk_container_set_border_width (GTK_CONTAINER (win), GUI_BORDER);
gtk_widget_set_opacity (win, (prefs.hex_gui_transparency / 255.)); gtk_widget_set_opacity (win, (prefs.hex_gui_transparency / 255.));
g_signal_connect (G_OBJECT (win), "focus-in-event", g_signal_connect (G_OBJECT (win), "focus_in_event",
G_CALLBACK (mg_topwin_focus_cb), sess); G_CALLBACK (mg_topwin_focus_cb), sess);
g_signal_connect (G_OBJECT (win), "destroy", g_signal_connect (G_OBJECT (win), "destroy",
G_CALLBACK (mg_topdestroy_cb), sess); G_CALLBACK (mg_topdestroy_cb), sess);
g_signal_connect (G_OBJECT (win), "configure-event", g_signal_connect (G_OBJECT (win), "configure_event",
G_CALLBACK (mg_configure_cb), sess); G_CALLBACK (mg_configure_cb), sess);
@@ -4336,15 +3943,15 @@ mg_create_tabwindow (session *sess)
gtk_widget_set_opacity (win, (prefs.hex_gui_transparency / 255.)); gtk_widget_set_opacity (win, (prefs.hex_gui_transparency / 255.));
gtk_container_set_border_width (GTK_CONTAINER (win), GUI_BORDER); gtk_container_set_border_width (GTK_CONTAINER (win), GUI_BORDER);
g_signal_connect (G_OBJECT (win), "delete-event", g_signal_connect (G_OBJECT (win), "delete_event",
G_CALLBACK (mg_tabwindow_de_cb), 0); G_CALLBACK (mg_tabwindow_de_cb), 0);
g_signal_connect (G_OBJECT (win), "destroy", g_signal_connect (G_OBJECT (win), "destroy",
G_CALLBACK (mg_tabwindow_kill_cb), 0); G_CALLBACK (mg_tabwindow_kill_cb), 0);
g_signal_connect (G_OBJECT (win), "focus-in-event", g_signal_connect (G_OBJECT (win), "focus_in_event",
G_CALLBACK (mg_tabwin_focus_cb), NULL); G_CALLBACK (mg_tabwin_focus_cb), NULL);
g_signal_connect (G_OBJECT (win), "configure-event", g_signal_connect (G_OBJECT (win), "configure_event",
G_CALLBACK (mg_configure_cb), NULL); G_CALLBACK (mg_configure_cb), NULL);
g_signal_connect (G_OBJECT (win), "window-state-event", g_signal_connect (G_OBJECT (win), "window_state_event",
G_CALLBACK (mg_windowstate_cb), NULL); G_CALLBACK (mg_windowstate_cb), NULL);
@@ -4481,8 +4088,7 @@ fe_clear_channel (session *sess)
if (!sess->gui->is_tab || sess == current_tab) if (!sess->gui->is_tab || sess == current_tab)
{ {
gtk_text_buffer_set_text ( gtk_entry_set_text (GTK_ENTRY (gui->topic_entry), "");
gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry)), "", -1);
if (gui->op_xpm) if (gui->op_xpm)
{ {

View File

@@ -869,9 +869,6 @@ menu_nickmenu (session *sess, GdkEventButton *event, char *nick, int num_sel)
static void static void
menu_showhide_cb (session *sess) menu_showhide_cb (session *sess)
{ {
if (!sess->gui->menu || !GTK_IS_WIDGET (sess->gui->menu))
return;
if (prefs.hex_gui_hide_menu) if (prefs.hex_gui_hide_menu)
gtk_widget_hide (sess->gui->menu); gtk_widget_hide (sess->gui->menu);
else else
@@ -929,11 +926,6 @@ menu_setting_foreach (void (*callback) (session *), int id, guint state)
while (list) while (list)
{ {
sess = list->data; sess = list->data;
if (!sess || !sess->gui)
{
list = list->next;
continue;
}
if (!sess->gui->is_tab || !maindone) if (!sess->gui->is_tab || !maindone)
{ {
@@ -943,22 +935,11 @@ menu_setting_foreach (void (*callback) (session *), int id, guint state)
{ {
GtkWidget *menu_item = sess->gui->menu_item[id]; GtkWidget *menu_item = sess->gui->menu_item[id];
if (menu_item != NULL && GTK_IS_CHECK_MENU_ITEM (menu_item)) if (menu_item != NULL)
{
guint toggled_signal = g_signal_lookup ("toggled", G_OBJECT_TYPE (menu_item));
if (toggled_signal != 0)
{
g_signal_handlers_block_matched (menu_item, G_SIGNAL_MATCH_ID, toggled_signal, 0, NULL, NULL, NULL);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), state);
g_signal_handlers_unblock_matched (menu_item, G_SIGNAL_MATCH_ID, toggled_signal, 0, NULL, NULL, NULL);
}
else
{ {
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), state); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), state);
} }
} }
}
if (callback) if (callback)
callback (sess); callback (sess);
} }
@@ -971,7 +952,7 @@ void
menu_bar_toggle (void) menu_bar_toggle (void)
{ {
prefs.hex_gui_hide_menu = !prefs.hex_gui_hide_menu; prefs.hex_gui_hide_menu = !prefs.hex_gui_hide_menu;
menu_setting_foreach (menu_showhide_cb, -1, !prefs.hex_gui_hide_menu); menu_setting_foreach (menu_showhide_cb, MENU_ID_MENUBAR, !prefs.hex_gui_hide_menu);
} }
static void static void
@@ -2189,11 +2170,6 @@ menu_foreach_gui (menu_entry *me, void (*callback) (GtkWidget *, menu_entry *, c
while (list) while (list)
{ {
sess = list->data; sess = list->data;
if (!sess || !sess->gui)
{
list = list->next;
continue;
}
/* do it only once for tab sessions, since they share a GUI */ /* do it only once for tab sessions, since they share a GUI */
if (!sess->gui->is_tab || !tabdone) if (!sess->gui->is_tab || !tabdone)
{ {
@@ -2622,7 +2598,6 @@ normalitem:
mymenu[i].key, mymenu[i].key,
mymenu[i].key == GDK_KEY_F1 ? 0 : mymenu[i].key == GDK_KEY_F1 ? 0 :
mymenu[i].key == GDK_KEY_w ? close_mask : mymenu[i].key == GDK_KEY_w ? close_mask :
mymenu[i].id == MENU_ID_AWAY ? away_mask :
(g_ascii_isupper (mymenu[i].key)) ? (g_ascii_isupper (mymenu[i].key)) ?
STATE_SHIFT | STATE_CTRL : STATE_SHIFT | STATE_CTRL :
STATE_CTRL, STATE_CTRL,

View File

@@ -28,7 +28,6 @@ zoitechat_gtk_sources = [
'maingui.c', 'maingui.c',
'notifygui.c', 'notifygui.c',
'pixmaps.c', 'pixmaps.c',
'preferences-persistence.c',
'plugin-tray.c', 'plugin-tray.c',
'plugin-notification.c', 'plugin-notification.c',
'rawlog.c', 'rawlog.c',

View File

@@ -1,66 +0,0 @@
#include "preferences-persistence.h"
#include "../common/cfgfiles.h"
#include "theme/theme-runtime.h"
PreferencesPersistenceResult
preferences_persistence_save_all (void)
{
PreferencesPersistenceResult result;
char *config_temp;
char *theme_temp;
result.success = FALSE;
result.retry_possible = TRUE;
result.partial_failure = FALSE;
result.config_failed = FALSE;
result.theme_failed = FALSE;
result.failed_file = NULL;
config_temp = NULL;
theme_temp = NULL;
if (!save_config_prepare (&config_temp))
{
result.config_failed = TRUE;
goto done;
}
if (!theme_runtime_save_prepare (&theme_temp))
{
result.theme_failed = TRUE;
goto done;
}
if (!save_config_finalize (config_temp))
{
result.config_failed = TRUE;
goto done;
}
if (!theme_runtime_save_finalize (theme_temp))
{
result.theme_failed = TRUE;
result.partial_failure = TRUE;
goto done;
}
result.success = TRUE;
done:
if (!result.success)
{
if (result.config_failed && result.theme_failed)
result.failed_file = "zoitechat.conf and colors.conf";
else if (result.config_failed)
result.failed_file = "zoitechat.conf";
else if (result.theme_failed)
result.failed_file = "colors.conf";
}
save_config_discard (config_temp);
theme_runtime_save_discard (theme_temp);
g_free (config_temp);
g_free (theme_temp);
return result;
}

View File

@@ -1,18 +0,0 @@
#ifndef ZOITECHAT_PREFERENCES_PERSISTENCE_H
#define ZOITECHAT_PREFERENCES_PERSISTENCE_H
#include <glib.h>
typedef struct
{
gboolean success;
gboolean retry_possible;
gboolean partial_failure;
gboolean config_failed;
gboolean theme_failed;
const char *failed_file;
} PreferencesPersistenceResult;
PreferencesPersistenceResult preferences_persistence_save_all (void);
#endif

View File

@@ -192,7 +192,7 @@ open_rawlog (struct server *serv)
serv, _("Save As...")); serv, _("Save As..."));
/* Copy selection to clipboard when Ctrl+Shift+C is pressed AND text auto-copy is disabled */ /* Copy selection to clipboard when Ctrl+Shift+C is pressed AND text auto-copy is disabled */
g_signal_connect (G_OBJECT (serv->gui->rawlog_window), "key-press-event", G_CALLBACK (rawlog_key_cb), serv->gui->rawlog_textlist); g_signal_connect (G_OBJECT (serv->gui->rawlog_window), "key_press_event", G_CALLBACK (rawlog_key_cb), serv->gui->rawlog_textlist);
g_object_set_data (G_OBJECT (serv->gui->rawlog_window), RAWLOG_THEME_LISTENER_ID_KEY, g_object_set_data (G_OBJECT (serv->gui->rawlog_window), RAWLOG_THEME_LISTENER_ID_KEY,
GUINT_TO_POINTER (theme_listener_register ("rawlog.window", rawlog_theme_changed, serv->gui->rawlog_window))); GUINT_TO_POINTER (theme_listener_register ("rawlog.window", rawlog_theme_changed, serv->gui->rawlog_window)));
g_signal_connect (G_OBJECT (serv->gui->rawlog_window), "destroy", G_CALLBACK (rawlog_theme_destroy_cb), NULL); g_signal_connect (G_OBJECT (serv->gui->rawlog_window), "destroy", G_CALLBACK (rawlog_theme_destroy_cb), NULL);

View File

@@ -763,9 +763,9 @@ servlist_edit_cb (GtkWidget *but, gpointer none)
servlist_servers_populate (selected_net, edit_trees[SERVER_TREE]); servlist_servers_populate (selected_net, edit_trees[SERVER_TREE]);
servlist_channels_populate (selected_net, edit_trees[CHANNEL_TREE]); servlist_channels_populate (selected_net, edit_trees[CHANNEL_TREE]);
servlist_commands_populate (selected_net, edit_trees[CMD_TREE]); servlist_commands_populate (selected_net, edit_trees[CMD_TREE]);
g_signal_connect (G_OBJECT (edit_win), "delete-event", g_signal_connect (G_OBJECT (edit_win), "delete_event",
G_CALLBACK (servlist_editwin_delete_cb), 0); G_CALLBACK (servlist_editwin_delete_cb), 0);
g_signal_connect (G_OBJECT (edit_win), "configure-event", g_signal_connect (G_OBJECT (edit_win), "configure_event",
G_CALLBACK (servlist_edit_configure_cb), 0); G_CALLBACK (servlist_edit_configure_cb), 0);
gtk_widget_show (edit_win); gtk_widget_show (edit_win);
} }
@@ -1002,8 +1002,7 @@ servlist_savegui (void)
sp[0] = 0; /* spaces will break the login */ sp[0] = 0; /* spaces will break the login */
/* strcpy (prefs.hex_irc_real_name, gtk_entry_get_text (GTK_ENTRY (entry_greal))); */ /* strcpy (prefs.hex_irc_real_name, gtk_entry_get_text (GTK_ENTRY (entry_greal))); */
servlist_save (); servlist_save ();
if (!save_config ()) save_config (); /* For nicks stored in zoitechat.conf */
fe_message (_("Could not save zoitechat.conf."), FE_MSG_WARN);
return 0; return 0;
} }
@@ -1839,7 +1838,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
model = GTK_TREE_MODEL (store); model = GTK_TREE_MODEL (store);
edit_trees[SERVER_TREE] = treeview_servers = gtk_tree_view_new_with_model (model); edit_trees[SERVER_TREE] = treeview_servers = gtk_tree_view_new_with_model (model);
g_signal_connect (G_OBJECT (treeview_servers), "key-press-event", g_signal_connect (G_OBJECT (treeview_servers), "key_press_event",
G_CALLBACK (servlist_keypress_cb), notebook); G_CALLBACK (servlist_keypress_cb), notebook);
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_servers))), g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_servers))),
"changed", G_CALLBACK (servlist_server_row_cb), NULL); "changed", G_CALLBACK (servlist_server_row_cb), NULL);
@@ -1864,7 +1863,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
model = GTK_TREE_MODEL (store); model = GTK_TREE_MODEL (store);
edit_trees[CHANNEL_TREE] = treeview_channels = gtk_tree_view_new_with_model (model); edit_trees[CHANNEL_TREE] = treeview_channels = gtk_tree_view_new_with_model (model);
g_signal_connect (G_OBJECT (treeview_channels), "key-press-event", g_signal_connect (G_OBJECT (treeview_channels), "key_press_event",
G_CALLBACK (servlist_keypress_cb), notebook); G_CALLBACK (servlist_keypress_cb), notebook);
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_channels))), g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_channels))),
"changed", G_CALLBACK (servlist_channel_row_cb), NULL); "changed", G_CALLBACK (servlist_channel_row_cb), NULL);
@@ -1901,7 +1900,7 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
model = GTK_TREE_MODEL (store); model = GTK_TREE_MODEL (store);
edit_trees[CMD_TREE] = treeview_commands = gtk_tree_view_new_with_model (model); edit_trees[CMD_TREE] = treeview_commands = gtk_tree_view_new_with_model (model);
g_signal_connect (G_OBJECT (treeview_commands), "key-press-event", g_signal_connect (G_OBJECT (treeview_commands), "key_press_event",
G_CALLBACK (servlist_keypress_cb), notebook); G_CALLBACK (servlist_keypress_cb), notebook);
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_commands))), g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_commands))),
"changed", G_CALLBACK (servlist_command_row_cb), NULL); "changed", G_CALLBACK (servlist_command_row_cb), NULL);
@@ -2357,13 +2356,13 @@ fe_serverlist_open (session *sess)
servlist_networks_populate (networks_tree, network_list); servlist_networks_populate (networks_tree, network_list);
g_signal_connect (G_OBJECT (serverlist_win), "delete-event", g_signal_connect (G_OBJECT (serverlist_win), "delete_event",
G_CALLBACK (servlist_delete_cb), 0); G_CALLBACK (servlist_delete_cb), 0);
g_signal_connect (G_OBJECT (serverlist_win), "configure-event", g_signal_connect (G_OBJECT (serverlist_win), "configure_event",
G_CALLBACK (servlist_configure_cb), 0); G_CALLBACK (servlist_configure_cb), 0);
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (networks_tree))), g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (networks_tree))),
"changed", G_CALLBACK (servlist_network_row_cb), NULL); "changed", G_CALLBACK (servlist_network_row_cb), NULL);
g_signal_connect (G_OBJECT (networks_tree), "key-press-event", g_signal_connect (G_OBJECT (networks_tree), "key_press_event",
G_CALLBACK (servlist_net_keypress_cb), networks_tree); G_CALLBACK (servlist_net_keypress_cb), networks_tree);
gtk_widget_show (serverlist_win); gtk_widget_show (serverlist_win);

View File

@@ -40,7 +40,6 @@
#include "maingui.h" #include "maingui.h"
#include "pixmaps.h" #include "pixmaps.h"
#include "menu.h" #include "menu.h"
#include "preferences-persistence.h"
#include "plugin-tray.h" #include "plugin-tray.h"
#include "notifications/notification-backend.h" #include "notifications/notification-backend.h"
@@ -894,7 +893,7 @@ setup_create_spin (GtkWidget *table, int row, const setting *set)
gtk_widget_set_tooltip_text (wid, _(set->tooltip)); gtk_widget_set_tooltip_text (wid, _(set->tooltip));
gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid), gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid),
setup_get_int (&setup_prefs, set)); setup_get_int (&setup_prefs, set));
g_signal_connect (G_OBJECT (wid), "value-changed", g_signal_connect (G_OBJECT (wid), "value_changed",
G_CALLBACK (setup_spin_cb), (gpointer)set); G_CALLBACK (setup_spin_cb), (gpointer)set);
gtk_box_pack_start (GTK_BOX (rbox), wid, 0, 0, 0); gtk_box_pack_start (GTK_BOX (rbox), wid, 0, 0, 0);
@@ -950,7 +949,7 @@ setup_create_hscale (GtkWidget *table, int row, const setting *set)
wid = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0., 255., 1.); wid = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0., 255., 1.);
gtk_scale_set_value_pos (GTK_SCALE (wid), GTK_POS_RIGHT); gtk_scale_set_value_pos (GTK_SCALE (wid), GTK_POS_RIGHT);
gtk_range_set_value (GTK_RANGE (wid), setup_get_int (&setup_prefs, set)); gtk_range_set_value (GTK_RANGE (wid), setup_get_int (&setup_prefs, set));
g_signal_connect (G_OBJECT(wid), "value-changed", g_signal_connect (G_OBJECT(wid), "value_changed",
G_CALLBACK (setup_hscale_cb), (gpointer)set); G_CALLBACK (setup_hscale_cb), (gpointer)set);
setup_table_attach (table, wid, 3, 6, row, row + 1, TRUE, FALSE, setup_table_attach (table, wid, 3, 6, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0); SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
@@ -1966,7 +1965,7 @@ setup_create_tree (GtkWidget *box, GtkWidget *book)
gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE); gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE);
gtk_tree_selection_set_select_function (sel, setup_tree_select_filter, gtk_tree_selection_set_select_function (sel, setup_tree_select_filter,
NULL, NULL); NULL, NULL);
g_signal_connect (G_OBJECT (tree), "cursor-changed", g_signal_connect (G_OBJECT (tree), "cursor_changed",
G_CALLBACK (setup_tree_cb), book); G_CALLBACK (setup_tree_cb), book);
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
@@ -2192,32 +2191,10 @@ setup_apply (struct zoitechatprefs *pr)
static void static void
setup_ok_cb (GtkWidget *but, GtkWidget *win) setup_ok_cb (GtkWidget *but, GtkWidget *win)
{ {
PreferencesPersistenceResult save_result;
struct zoitechatprefs old_prefs;
char buffer[192];
memcpy (&old_prefs, &prefs, sizeof (prefs));
theme_preferences_stage_apply ();
setup_apply (&setup_prefs);
save_result = preferences_persistence_save_all ();
if (save_result.success)
{
theme_preferences_stage_commit ();
gtk_widget_destroy (win); gtk_widget_destroy (win);
return; setup_apply (&setup_prefs);
} save_config ();
theme_manager_save_preferences ();
memcpy (&prefs, &old_prefs, sizeof (prefs));
theme_preferences_stage_discard ();
if (save_result.partial_failure)
{
fe_message (_("Preferences were partially saved. zoitechat.conf succeeded, colors.conf failed. Retry is possible."), FE_MSG_ERROR);
return;
}
g_snprintf (buffer, sizeof (buffer), _("Could not save preferences (%s). Retry is possible."), save_result.failed_file ? save_result.failed_file : _("unknown file"));
fe_message (buffer, FE_MSG_ERROR);
} }
static GtkWidget * static GtkWidget *
@@ -2265,7 +2242,6 @@ setup_close_cb (GtkWidget *win, GtkWidget **swin)
{ {
*swin = NULL; *swin = NULL;
theme_preferences_stage_discard ();
if (font_dialog) if (font_dialog)
{ {
@@ -2286,7 +2262,6 @@ setup_open (void)
memcpy (&setup_prefs, &prefs, sizeof (prefs)); memcpy (&setup_prefs, &prefs, sizeof (prefs));
color_change = FALSE; color_change = FALSE;
theme_preferences_stage_begin ();
setup_window = setup_window_open (); setup_window = setup_window_open ();
g_signal_connect (G_OBJECT (setup_window), "destroy", g_signal_connect (G_OBJECT (setup_window), "destroy",

View File

@@ -964,9 +964,6 @@ default_word_check(SexySpellEntry *entry, const gchar *word)
/* We only want to check words */ /* We only want to check words */
return FALSE; return FALSE;
} }
if (g_utf8_strlen (word, -1) > 20)
return FALSE;
for (li = entry->priv->dict_list; li; li = g_slist_next (li)) { for (li = entry->priv->dict_list; li; li = g_slist_next (li)) {
struct EnchantDict *dict = (struct EnchantDict *) li->data; struct EnchantDict *dict = (struct EnchantDict *) li->data;
if (enchant_dict_check(dict, word, strlen(word)) == 0) { if (enchant_dict_check(dict, word, strlen(word)) == 0) {
@@ -1164,34 +1161,13 @@ check_color:
} }
} }
static gboolean
attr_list_has_attrs (PangoAttrList *attrs)
{
PangoAttrIterator *it;
GSList *list;
gboolean has = FALSE;
if (!attrs)
return FALSE;
it = pango_attr_list_get_iterator (attrs);
if (!it)
return FALSE;
list = pango_attr_iterator_get_attrs (it);
has = (list != NULL);
g_slist_free_full (list, (GDestroyNotify) pango_attribute_destroy);
pango_attr_iterator_destroy (it);
return has;
}
static void static void
sexy_spell_entry_recheck_all(SexySpellEntry *entry) sexy_spell_entry_recheck_all(SexySpellEntry *entry)
{ {
GdkRectangle rect; GdkRectangle rect;
GtkAllocation allocation; GtkAllocation allocation;
GtkWidget *widget = GTK_WIDGET(entry); GtkWidget *widget = GTK_WIDGET(entry);
PangoLayout *layout;
int length, i, text_len; int length, i, text_len;
const char *text; const char *text;
@@ -1220,7 +1196,8 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
} }
} }
gtk_entry_set_attributes (GTK_ENTRY (entry), attr_list_has_attrs (entry->priv->attr_list) ? entry->priv->attr_list : NULL); layout = gtk_entry_get_layout(GTK_ENTRY(entry));
pango_layout_set_attributes(layout, entry->priv->attr_list);
if (gtk_widget_get_realized (GTK_WIDGET(entry))) if (gtk_widget_get_realized (GTK_WIDGET(entry)))
{ {
@@ -1236,6 +1213,13 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
static gboolean static gboolean
sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr) sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr)
{ {
SexySpellEntry *entry = SEXY_SPELL_ENTRY(widget);
GtkEntry *gtk_entry = GTK_ENTRY(widget);
PangoLayout *layout;
layout = gtk_entry_get_layout(gtk_entry);
pango_layout_set_attributes(layout, entry->priv->attr_list);
return GTK_WIDGET_CLASS(parent_class)->draw (widget, cr); return GTK_WIDGET_CLASS(parent_class)->draw (widget, cr);
} }

View File

@@ -57,10 +57,9 @@ theme_runtime_load (void)
{ {
} }
gboolean void
theme_runtime_save (void) theme_runtime_save (void)
{ {
return TRUE;
} }
void void

View File

@@ -119,9 +119,8 @@ void theme_runtime_load (void)
{ {
} }
gboolean theme_runtime_save (void) void theme_runtime_save (void)
{ {
return TRUE;
} }
gboolean theme_runtime_is_dark_active (void) gboolean theme_runtime_is_dark_active (void)

View File

@@ -112,9 +112,8 @@ void theme_runtime_load (void)
{ {
} }
gboolean theme_runtime_save (void) void theme_runtime_save (void)
{ {
return TRUE;
} }
gboolean theme_runtime_is_dark_active (void) gboolean theme_runtime_is_dark_active (void)

View File

@@ -122,9 +122,8 @@ void theme_runtime_load (void)
{ {
} }
gboolean theme_runtime_save (void) void theme_runtime_save (void)
{ {
return TRUE;
} }
gboolean theme_runtime_is_dark_active (void) gboolean theme_runtime_is_dark_active (void)

View File

@@ -66,10 +66,9 @@ theme_manager_reset_mode_colors (unsigned int mode, gboolean *palette_changed)
*palette_changed = FALSE; *palette_changed = FALSE;
} }
gboolean void
theme_manager_save_preferences (void) theme_manager_save_preferences (void)
{ {
return TRUE;
} }
ThemePaletteBehavior ThemePaletteBehavior

View File

@@ -19,12 +19,6 @@ struct zoitechatprefs prefs;
static char *test_home_dir; static char *test_home_dir;
static char *
test_home_path (const char *file)
{
return g_build_filename (test_home_dir, file, NULL);
}
static gboolean static gboolean
read_line_value (const char *cfg, const char *key, char *out, gsize out_len) read_line_value (const char *cfg, const char *key, char *out, gsize out_len)
{ {
@@ -103,12 +97,6 @@ cfg_put_int (int fh, int value, char *var)
return write (fh, line, (size_t) len) == len; return write (fh, line, (size_t) len) == len;
} }
char *
get_xdir (void)
{
return test_home_dir;
}
int int
zoitechat_open_file (const char *file, int flags, int mode, int xof_flags) zoitechat_open_file (const char *file, int flags, int mode, int xof_flags)
{ {
@@ -157,7 +145,7 @@ read_colors_conf (void)
gsize length = 0; gsize length = 0;
gboolean ok; gboolean ok;
path = test_home_path ("colors.conf"); path = g_build_filename (test_home_dir, "colors.conf", NULL);
ok = g_file_get_contents (path, &content, &length, NULL); ok = g_file_get_contents (path, &content, &length, NULL);
g_free (path); g_free (path);
g_assert_true (ok); g_assert_true (ok);
@@ -234,7 +222,7 @@ test_loads_legacy_color_keys_via_migration_loader (void)
gboolean ok; gboolean ok;
setup_temp_home (); setup_temp_home ();
path = test_home_path ("colors.conf"); path = g_build_filename (test_home_dir, "colors.conf", NULL);
ok = g_file_set_contents (path, legacy_cfg, -1, NULL); ok = g_file_set_contents (path, legacy_cfg, -1, NULL);
g_free (path); g_free (path);
g_assert_true (ok); g_assert_true (ok);
@@ -348,50 +336,6 @@ test_gtk_map_uses_theme_defaults_until_custom_token_is_set (void)
g_assert_true (colors_equal (&values.foreground, &custom)); g_assert_true (colors_equal (&values.foreground, &custom));
} }
static void
test_save_finalize_replaces_colors_conf_atomically (void)
{
char *path;
char *temp_path = NULL;
char *cfg = NULL;
gboolean ok;
setup_temp_home ();
path = test_home_path ("colors.conf");
ok = g_file_set_contents (path, "theme.mode.light.token.mirc_0 = 0000 0000 0000\n", -1, NULL);
g_assert_true (ok);
theme_runtime_load ();
g_assert_true (theme_runtime_save_prepare (&temp_path));
g_assert_nonnull (temp_path);
g_assert_nonnull (g_strrstr (temp_path, "colors.conf.new."));
g_assert_true (g_file_test (temp_path, G_FILE_TEST_EXISTS));
g_assert_true (theme_runtime_save_finalize (temp_path));
g_assert_false (g_file_test (temp_path, G_FILE_TEST_EXISTS));
ok = g_file_get_contents (path, &cfg, NULL, NULL);
g_assert_true (ok);
g_assert_nonnull (g_strstr_len (cfg, -1, "theme.palette.semantic_migrated = 1"));
g_free (cfg);
g_free (temp_path);
g_free (path);
}
static void
test_save_discard_unlinks_temp_file (void)
{
char *temp_path = NULL;
setup_temp_home ();
theme_runtime_load ();
g_assert_true (theme_runtime_save_prepare (&temp_path));
g_assert_nonnull (temp_path);
g_assert_true (g_file_test (temp_path, G_FILE_TEST_EXISTS));
theme_runtime_save_discard (temp_path);
g_assert_false (g_file_test (temp_path, G_FILE_TEST_EXISTS));
g_free (temp_path);
}
static void static void
test_save_writes_only_custom_token_keys (void) test_save_writes_only_custom_token_keys (void)
{ {
@@ -424,10 +368,6 @@ main (int argc, char **argv)
test_gtk_map_colors_blend_with_palette_without_transparency); test_gtk_map_colors_blend_with_palette_without_transparency);
g_test_add_func ("/theme/runtime/gtk_map_uses_theme_defaults_until_custom_token_is_set", g_test_add_func ("/theme/runtime/gtk_map_uses_theme_defaults_until_custom_token_is_set",
test_gtk_map_uses_theme_defaults_until_custom_token_is_set); test_gtk_map_uses_theme_defaults_until_custom_token_is_set);
g_test_add_func ("/theme/runtime/save_finalize_replaces_colors_conf_atomically",
test_save_finalize_replaces_colors_conf_atomically);
g_test_add_func ("/theme/runtime/save_discard_unlinks_temp_file",
test_save_discard_unlinks_temp_file);
g_test_add_func ("/theme/runtime/save_writes_only_custom_token_keys", g_test_add_func ("/theme/runtime/save_writes_only_custom_token_keys",
test_save_writes_only_custom_token_keys); test_save_writes_only_custom_token_keys);
return g_test_run (); return g_test_run ();

View File

@@ -27,12 +27,6 @@ typedef struct
guint16 bg_red; guint16 bg_red;
guint16 bg_green; guint16 bg_green;
guint16 bg_blue; guint16 bg_blue;
guint16 sel_fg_red;
guint16 sel_fg_green;
guint16 sel_fg_blue;
guint16 sel_bg_red;
guint16 sel_bg_green;
guint16 sel_bg_blue;
} ThemeCssInputFingerprint; } ThemeCssInputFingerprint;
static GtkCssProvider *theme_css_input_provider; static GtkCssProvider *theme_css_input_provider;
@@ -98,12 +92,6 @@ theme_css_input_fingerprint_matches (const ThemeCssInputFingerprint *next)
if (theme_css_input_fp.bg_red != next->bg_red || theme_css_input_fp.bg_green != next->bg_green if (theme_css_input_fp.bg_red != next->bg_red || theme_css_input_fp.bg_green != next->bg_green
|| theme_css_input_fp.bg_blue != next->bg_blue) || theme_css_input_fp.bg_blue != next->bg_blue)
return FALSE; return FALSE;
if (theme_css_input_fp.sel_fg_red != next->sel_fg_red || theme_css_input_fp.sel_fg_green != next->sel_fg_green
|| theme_css_input_fp.sel_fg_blue != next->sel_fg_blue)
return FALSE;
if (theme_css_input_fp.sel_bg_red != next->sel_bg_red || theme_css_input_fp.sel_bg_green != next->sel_bg_green
|| theme_css_input_fp.sel_bg_blue != next->sel_bg_blue)
return FALSE;
if (g_strcmp0 (theme_css_input_fp.theme_name, next->theme_name) != 0) if (g_strcmp0 (theme_css_input_fp.theme_name, next->theme_name) != 0)
return FALSE; return FALSE;
if (g_strcmp0 (theme_css_input_fp.font, next->font) != 0) if (g_strcmp0 (theme_css_input_fp.font, next->font) != 0)
@@ -131,9 +119,7 @@ theme_css_input_fingerprint_clear (void)
static char * static char *
theme_css_build_input (const char *theme_name, guint16 fg_red, guint16 fg_green, guint16 fg_blue, theme_css_build_input (const char *theme_name, guint16 fg_red, guint16 fg_green, guint16 fg_blue,
guint16 bg_red, guint16 bg_green, guint16 bg_blue, guint16 bg_red, guint16 bg_green, guint16 bg_blue)
guint16 sel_fg_red, guint16 sel_fg_green, guint16 sel_fg_blue,
guint16 sel_bg_red, guint16 sel_bg_green, guint16 sel_bg_blue)
{ {
GString *css = g_string_new (""); GString *css = g_string_new ("");
@@ -151,11 +137,6 @@ theme_css_build_input (const char *theme_name, guint16 fg_red, guint16 fg_green,
"%s {" "%s {"
"color: #%02x%02x%02x;" "color: #%02x%02x%02x;"
"caret-color: #%02x%02x%02x;" "caret-color: #%02x%02x%02x;"
"}"
"%s selection, %s text selection, %s:focus selection, %s:focus text selection, %s *:selected, %s *:selected:focus {"
"background-color: #%02x%02x%02x;"
"color: #%02x%02x%02x;"
"text-shadow: none;"
"}", "}",
theme_css_selector_input, theme_css_selector_input,
(bg_red >> 8), (bg_green >> 8), (bg_blue >> 8), (bg_red >> 8), (bg_green >> 8), (bg_blue >> 8),
@@ -163,15 +144,7 @@ theme_css_build_input (const char *theme_name, guint16 fg_red, guint16 fg_green,
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8), (fg_red >> 8), (fg_green >> 8), (fg_blue >> 8),
theme_css_selector_input_text, theme_css_selector_input_text,
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8), (fg_red >> 8), (fg_green >> 8), (fg_blue >> 8),
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8), (fg_red >> 8), (fg_green >> 8), (fg_blue >> 8));
theme_css_selector_input,
theme_css_selector_input,
theme_css_selector_input,
theme_css_selector_input,
theme_css_selector_input,
theme_css_selector_input,
(sel_bg_red >> 8), (sel_bg_green >> 8), (sel_bg_blue >> 8),
(sel_fg_red >> 8), (sel_fg_green >> 8), (sel_fg_blue >> 8));
return g_string_free (css, FALSE); return g_string_free (css, FALSE);
} }
@@ -204,10 +177,6 @@ theme_css_reload_input_style (gboolean enabled, const PangoFontDescription *font
&next.fg_red, &next.fg_green, &next.fg_blue); &next.fg_red, &next.fg_green, &next.fg_blue);
theme_palette_color_get_rgb16 (&style_values.background, theme_palette_color_get_rgb16 (&style_values.background,
&next.bg_red, &next.bg_green, &next.bg_blue); &next.bg_red, &next.bg_green, &next.bg_blue);
theme_palette_color_get_rgb16 (&style_values.selection_foreground,
&next.sel_fg_red, &next.sel_fg_green, &next.sel_fg_blue);
theme_palette_color_get_rgb16 (&style_values.selection_background,
&next.sel_bg_red, &next.sel_bg_green, &next.sel_bg_blue);
next.colors_set = TRUE; next.colors_set = TRUE;
} }
@@ -224,9 +193,7 @@ theme_css_reload_input_style (gboolean enabled, const PangoFontDescription *font
css = theme_css_build_input (theme_name ? theme_name : "", css = theme_css_build_input (theme_name ? theme_name : "",
next.fg_red, next.fg_green, next.fg_blue, next.fg_red, next.fg_green, next.fg_blue,
next.bg_red, next.bg_green, next.bg_blue, next.bg_red, next.bg_green, next.bg_blue);
next.sel_fg_red, next.sel_fg_green, next.sel_fg_blue,
next.sel_bg_red, next.sel_bg_green, next.sel_bg_blue);
gtk_css_provider_load_from_data (theme_css_input_provider, css, -1, NULL); gtk_css_provider_load_from_data (theme_css_input_provider, css, -1, NULL);
g_free (css); g_free (css);
theme_css_apply_app_provider (GTK_STYLE_PROVIDER (theme_css_input_provider)); theme_css_apply_app_provider (GTK_STYLE_PROVIDER (theme_css_input_provider));
@@ -309,7 +276,7 @@ theme_css_apply_palette_widget (GtkWidget *widget, const GdkRGBA *bg, const GdkR
if (fg) if (fg)
g_string_append_printf (css, " color: %s;", fg_color); g_string_append_printf (css, " color: %s;", fg_color);
g_string_append (css, " }"); g_string_append (css, " }");
g_string_append_printf (css, ".%s *:selected, .%s *:selected:focus, .%s *:selected:hover, .%s treeview.view:selected, .%s treeview.view:selected:focus, .%s treeview.view:selected:hover, .%s row:selected, .%s row:selected:focus, .%s row:selected:hover, .%s selection, .%s text selection, .%s entry selection, .%s entry text selection, .%s:focus selection, .%s:focus text selection {", theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class); g_string_append_printf (css, ".%s *:selected, .%s *:selected:focus, .%s *:selected:hover, .%s treeview.view:selected, .%s treeview.view:selected:focus, .%s treeview.view:selected:hover, .%s row:selected, .%s row:selected:focus, .%s row:selected:hover {", theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class, theme_css_selector_palette_class);
if (sel_bg_color) if (sel_bg_color)
g_string_append_printf (css, " background-color: %s;", sel_bg_color); g_string_append_printf (css, " background-color: %s;", sel_bg_color);
else if (bg) else if (bg)

View File

@@ -284,10 +284,10 @@ theme_manager_commit_preferences (unsigned int old_mode, gboolean *color_change)
fe_set_auto_dark_mode_state (theme_policy_is_dark_mode_active (ZOITECHAT_DARK_MODE_AUTO)); fe_set_auto_dark_mode_state (theme_policy_is_dark_mode_active (ZOITECHAT_DARK_MODE_AUTO));
} }
gboolean void
theme_manager_save_preferences (void) theme_manager_save_preferences (void)
{ {
return theme_runtime_save (); theme_runtime_save ();
} }
gboolean gboolean

View File

@@ -43,7 +43,7 @@ void theme_manager_set_mode (unsigned int mode, gboolean *palette_changed);
void theme_manager_set_token_color (unsigned int mode, ThemeSemanticToken token, const GdkRGBA *color, gboolean *palette_changed); void theme_manager_set_token_color (unsigned int mode, ThemeSemanticToken token, const GdkRGBA *color, gboolean *palette_changed);
void theme_manager_reset_mode_colors (unsigned int mode, gboolean *palette_changed); void theme_manager_reset_mode_colors (unsigned int mode, gboolean *palette_changed);
void theme_manager_commit_preferences (unsigned int old_mode, gboolean *color_change); void theme_manager_commit_preferences (unsigned int old_mode, gboolean *color_change);
gboolean theme_manager_save_preferences (void); void theme_manager_save_preferences (void);
gboolean theme_changed_event_has_reason (const ThemeChangedEvent *event, ThemeChangedReason reason); gboolean theme_changed_event_has_reason (const ThemeChangedEvent *event, ThemeChangedReason reason);
void theme_manager_apply_and_dispatch (unsigned int mode, ThemeChangedReason reasons, gboolean *palette_changed); void theme_manager_apply_and_dispatch (unsigned int mode, ThemeChangedReason reasons, gboolean *palette_changed);
void theme_manager_dispatch_changed (ThemeChangedReason reasons); void theme_manager_dispatch_changed (ThemeChangedReason reasons);

View File

@@ -70,155 +70,6 @@ typedef struct
#define COLOR_MANAGER_RESPONSE_RESET 1 #define COLOR_MANAGER_RESPONSE_RESET 1
typedef struct
{
gboolean active;
gboolean changed;
gboolean snapshot_valid[THEME_TOKEN_COUNT];
gboolean staged_valid[THEME_TOKEN_COUNT];
GdkRGBA snapshot[THEME_TOKEN_COUNT];
GdkRGBA staged[THEME_TOKEN_COUNT];
} theme_preferences_stage_state;
static theme_preferences_stage_state theme_preferences_stage;
static gboolean
theme_preferences_staged_get_color (ThemeSemanticToken token, GdkRGBA *rgba)
{
if (token < 0 || token >= THEME_TOKEN_COUNT || !rgba)
return FALSE;
if (theme_preferences_stage.active && theme_preferences_stage.staged_valid[token])
{
*rgba = theme_preferences_stage.staged[token];
return TRUE;
}
return theme_get_color (token, rgba);
}
static void
theme_preferences_stage_recompute_changed (void)
{
ThemeSemanticToken token;
theme_preferences_stage.changed = FALSE;
for (token = THEME_TOKEN_MIRC_0; token < THEME_TOKEN_COUNT; token++)
{
if (!theme_preferences_stage.snapshot_valid[token] || !theme_preferences_stage.staged_valid[token])
continue;
if (!gdk_rgba_equal (&theme_preferences_stage.snapshot[token], &theme_preferences_stage.staged[token]))
{
theme_preferences_stage.changed = TRUE;
return;
}
}
}
static void
theme_preferences_stage_sync_runtime_to_snapshot (void)
{
ThemeSemanticToken token;
for (token = THEME_TOKEN_MIRC_0; token < THEME_TOKEN_COUNT; token++)
{
if (theme_preferences_stage.snapshot_valid[token])
theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT, token,
&theme_preferences_stage.snapshot[token], NULL);
}
}
static void
theme_preferences_stage_sync_runtime_to_staged (void)
{
ThemeSemanticToken token;
for (token = THEME_TOKEN_MIRC_0; token < THEME_TOKEN_COUNT; token++)
{
if (theme_preferences_stage.staged_valid[token])
theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT, token,
&theme_preferences_stage.staged[token], NULL);
}
}
static void
theme_preferences_staged_set_color (ThemeSemanticToken token, const GdkRGBA *rgba,
gboolean *color_change_flag, gboolean live_preview)
{
const GdkRGBA *preview_color = rgba;
if (token < 0 || token >= THEME_TOKEN_COUNT || !rgba)
return;
if (theme_preferences_stage.active)
{
theme_preferences_stage.staged[token] = *rgba;
theme_preferences_stage.staged_valid[token] = TRUE;
theme_preferences_stage_recompute_changed ();
if (color_change_flag)
*color_change_flag = theme_preferences_stage.changed;
preview_color = &theme_preferences_stage.staged[token];
}
if (live_preview)
theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT, token, preview_color, NULL);
}
void
theme_preferences_stage_begin (void)
{
ThemeSemanticToken token;
memset (&theme_preferences_stage, 0, sizeof (theme_preferences_stage));
theme_preferences_stage.active = TRUE;
for (token = THEME_TOKEN_MIRC_0; token < THEME_TOKEN_COUNT; token++)
{
GdkRGBA rgba;
if (!theme_preferences_staged_get_color (token, &rgba))
continue;
theme_preferences_stage.snapshot[token] = rgba;
theme_preferences_stage.staged[token] = rgba;
theme_preferences_stage.snapshot_valid[token] = TRUE;
theme_preferences_stage.staged_valid[token] = TRUE;
}
}
void
theme_preferences_stage_apply (void)
{
if (!theme_preferences_stage.active)
return;
theme_preferences_stage_sync_runtime_to_staged ();
}
void
theme_preferences_stage_commit (void)
{
if (!theme_preferences_stage.active)
return;
theme_preferences_stage_apply ();
memset (&theme_preferences_stage, 0, sizeof (theme_preferences_stage));
}
void
theme_preferences_stage_discard (void)
{
if (!theme_preferences_stage.active)
return;
theme_preferences_stage_sync_runtime_to_snapshot ();
memset (&theme_preferences_stage, 0, sizeof (theme_preferences_stage));
}
static void
theme_preferences_show_import_error (GtkWidget *button, const char *message);
static void static void
theme_preferences_manager_row_free (gpointer data) theme_preferences_manager_row_free (gpointer data)
{ {
@@ -262,16 +113,16 @@ theme_preferences_manager_update_preview (theme_color_manager_ui *ui)
if (!ui) if (!ui)
return; return;
if (!theme_preferences_staged_get_color (THEME_TOKEN_TEXT_FOREGROUND, &text_fg) if (!theme_get_color (THEME_TOKEN_TEXT_FOREGROUND, &text_fg)
|| !theme_preferences_staged_get_color (THEME_TOKEN_TEXT_BACKGROUND, &text_bg) || !theme_get_color (THEME_TOKEN_TEXT_BACKGROUND, &text_bg)
|| !theme_preferences_staged_get_color (THEME_TOKEN_SELECTION_FOREGROUND, &sel_fg) || !theme_get_color (THEME_TOKEN_SELECTION_FOREGROUND, &sel_fg)
|| !theme_preferences_staged_get_color (THEME_TOKEN_SELECTION_BACKGROUND, &sel_bg) || !theme_get_color (THEME_TOKEN_SELECTION_BACKGROUND, &sel_bg)
|| !theme_preferences_staged_get_color (THEME_TOKEN_MARKER, &marker) || !theme_get_color (THEME_TOKEN_MARKER, &marker)
|| !theme_preferences_staged_get_color (THEME_TOKEN_TAB_NEW_DATA, &tab_new_data) || !theme_get_color (THEME_TOKEN_TAB_NEW_DATA, &tab_new_data)
|| !theme_preferences_staged_get_color (THEME_TOKEN_TAB_NEW_MESSAGE, &tab_new_message) || !theme_get_color (THEME_TOKEN_TAB_NEW_MESSAGE, &tab_new_message)
|| !theme_preferences_staged_get_color (THEME_TOKEN_TAB_HIGHLIGHT, &tab_highlight) || !theme_get_color (THEME_TOKEN_TAB_HIGHLIGHT, &tab_highlight)
|| !theme_preferences_staged_get_color (THEME_TOKEN_TAB_AWAY, &tab_away) || !theme_get_color (THEME_TOKEN_TAB_AWAY, &tab_away)
|| !theme_preferences_staged_get_color (THEME_TOKEN_SPELL, &spell)) || !theme_get_color (THEME_TOKEN_SPELL, &spell))
return; return;
gtkutil_apply_palette (ui->preview_window, &text_bg, &text_fg, NULL); gtkutil_apply_palette (ui->preview_window, &text_bg, &text_fg, NULL);
@@ -451,12 +302,15 @@ theme_preferences_color_response_cb (GtkDialog *dialog, gint response_id, gpoint
if (response_id == GTK_RESPONSE_OK) if (response_id == GTK_RESPONSE_OK)
{ {
GdkRGBA rgba; GdkRGBA rgba;
gboolean changed = FALSE;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &rgba); gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &rgba);
theme_preferences_staged_set_color (data->token, theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT,
data->token,
&rgba, &rgba,
data->color_change_flag, &changed);
TRUE); if (data->color_change_flag)
*data->color_change_flag = *data->color_change_flag || changed;
theme_preferences_color_button_apply (data->button, &rgba); theme_preferences_color_button_apply (data->button, &rgba);
theme_preferences_manager_update_preview ((theme_color_manager_ui *) data->manager_ui); theme_preferences_manager_update_preview ((theme_color_manager_ui *) data->manager_ui);
} }
@@ -475,7 +329,7 @@ theme_preferences_color_cb (GtkWidget *button, gpointer userdata)
token = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "zoitechat-theme-token")); token = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "zoitechat-theme-token"));
if (!theme_preferences_staged_get_color (token, &rgba)) if (!theme_get_color (token, &rgba))
return; return;
dialog = gtk_color_chooser_dialog_new (_("Select color"), GTK_WINDOW (userdata)); dialog = gtk_color_chooser_dialog_new (_("Select color"), GTK_WINDOW (userdata));
theme_manager_attach_window (dialog); theme_manager_attach_window (dialog);
@@ -551,7 +405,14 @@ theme_preferences_manager_row_apply (theme_color_manager_row *row, const GdkRGBA
static void static void
theme_preferences_manager_row_commit (theme_color_manager_row *row, const GdkRGBA *rgba) theme_preferences_manager_row_commit (theme_color_manager_row *row, const GdkRGBA *rgba)
{ {
theme_preferences_staged_set_color (row->token, rgba, row->color_change_flag, TRUE); gboolean changed = FALSE;
theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT,
row->token,
rgba,
&changed);
if (row->color_change_flag)
*row->color_change_flag = *row->color_change_flag || changed;
theme_preferences_manager_row_apply (row, rgba); theme_preferences_manager_row_apply (row, rgba);
theme_preferences_manager_update_preview ((theme_color_manager_ui *) row->manager_ui); theme_preferences_manager_update_preview ((theme_color_manager_ui *) row->manager_ui);
} }
@@ -564,7 +425,7 @@ theme_preferences_manager_entry_commit (theme_color_manager_row *row)
if (!gdk_rgba_parse (&rgba, text)) if (!gdk_rgba_parse (&rgba, text))
{ {
if (theme_preferences_staged_get_color (row->token, &rgba)) if (theme_get_color (row->token, &rgba))
theme_preferences_manager_row_apply (row, &rgba); theme_preferences_manager_row_apply (row, &rgba);
return; return;
} }
@@ -622,7 +483,7 @@ theme_preferences_manager_pick_cb (GtkWidget *button, gpointer user_data)
GdkRGBA rgba; GdkRGBA rgba;
theme_manager_live_picker_data *data; theme_manager_live_picker_data *data;
if (!theme_preferences_staged_get_color (row->token, &rgba)) if (!theme_get_color (row->token, &rgba))
return; return;
dialog = gtk_color_chooser_dialog_new (_("Select color"), row->parent); dialog = gtk_color_chooser_dialog_new (_("Select color"), row->parent);
@@ -681,7 +542,7 @@ theme_preferences_manager_refresh_rows (theme_color_manager_ui *ui)
theme_color_manager_row *row = g_ptr_array_index (ui->rows, i); theme_color_manager_row *row = g_ptr_array_index (ui->rows, i);
GdkRGBA rgba; GdkRGBA rgba;
if (theme_preferences_staged_get_color (row->token, &rgba)) if (theme_get_color (row->token, &rgba))
theme_preferences_manager_row_apply (row, &rgba); theme_preferences_manager_row_apply (row, &rgba);
} }
@@ -700,24 +561,7 @@ theme_preferences_manager_dialog_response_cb (GtkDialog *dialog, gint response_i
gboolean changed = FALSE; gboolean changed = FALSE;
theme_manager_reset_mode_colors (ZOITECHAT_DARK_MODE_LIGHT, &changed); theme_manager_reset_mode_colors (ZOITECHAT_DARK_MODE_LIGHT, &changed);
if (theme_preferences_stage.active)
{
ThemeSemanticToken token;
for (token = THEME_TOKEN_MIRC_0; token < THEME_TOKEN_COUNT; token++)
{
GdkRGBA rgba;
if (!theme_get_color (token, &rgba))
continue;
theme_preferences_stage.staged[token] = rgba;
theme_preferences_stage.staged_valid[token] = TRUE;
}
theme_preferences_stage_recompute_changed ();
if (ui->color_change_flag) if (ui->color_change_flag)
*ui->color_change_flag = theme_preferences_stage.changed;
}
else if (ui->color_change_flag)
*ui->color_change_flag = *ui->color_change_flag || changed; *ui->color_change_flag = *ui->color_change_flag || changed;
} }
@@ -851,7 +695,7 @@ theme_preferences_create_color_manager_dialog (GtkWindow *parent, gboolean *colo
g_free (token_code); g_free (token_code);
g_free (search_text); g_free (search_text);
if (theme_preferences_staged_get_color (token, &rgba)) if (theme_get_color (token, &rgba))
theme_preferences_manager_row_apply (row, &rgba); theme_preferences_manager_row_apply (row, &rgba);
g_signal_connect (G_OBJECT (button), "clicked", g_signal_connect (G_OBJECT (button), "clicked",
@@ -880,15 +724,19 @@ static void
theme_preferences_manage_colors_cb (GtkWidget *button, gpointer user_data) theme_preferences_manage_colors_cb (GtkWidget *button, gpointer user_data)
{ {
gboolean *color_change_flag = user_data; gboolean *color_change_flag = user_data;
gboolean old_changed = FALSE;
GtkWidget *dialog; GtkWidget *dialog;
if (color_change_flag)
old_changed = *color_change_flag;
dialog = theme_preferences_create_color_manager_dialog (GTK_WINDOW (gtk_widget_get_toplevel (button)), dialog = theme_preferences_create_color_manager_dialog (GTK_WINDOW (gtk_widget_get_toplevel (button)),
color_change_flag); color_change_flag);
gtk_dialog_run (GTK_DIALOG (dialog)); gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog); gtk_widget_destroy (dialog);
if (color_change_flag) if (color_change_flag && *color_change_flag != old_changed)
*color_change_flag = theme_preferences_stage.active ? theme_preferences_stage.changed : *color_change_flag; theme_manager_save_preferences ();
} }
static void static void
@@ -1017,8 +865,12 @@ theme_preferences_import_colors_conf_cb (GtkWidget *button, gpointer user_data)
char *cfg; char *cfg;
GError *error = NULL; GError *error = NULL;
gboolean any_imported = FALSE; gboolean any_imported = FALSE;
gboolean old_changed = FALSE;
ThemeSemanticToken token; ThemeSemanticToken token;
if (color_change_flag)
old_changed = *color_change_flag;
dialog = gtk_file_chooser_dialog_new (_("Import colors.conf colors"), dialog = gtk_file_chooser_dialog_new (_("Import colors.conf colors"),
GTK_WINDOW (gtk_widget_get_toplevel (button)), GTK_WINDOW (gtk_widget_get_toplevel (button)),
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -1054,14 +906,14 @@ theme_preferences_import_colors_conf_cb (GtkWidget *button, gpointer user_data)
if (!theme_preferences_read_import_color (cfg, token, &rgba)) if (!theme_preferences_read_import_color (cfg, token, &rgba))
continue; continue;
theme_preferences_staged_set_color (token, &rgba, color_change_flag, TRUE); theme_manager_set_token_color (ZOITECHAT_DARK_MODE_LIGHT, token, &rgba, color_change_flag);
any_imported = TRUE; any_imported = TRUE;
} }
if (!any_imported) if (!any_imported)
theme_preferences_show_import_error (button, _("No importable colors were found in that colors.conf file.")); theme_preferences_show_import_error (button, _("No importable colors were found in that colors.conf file."));
else if (color_change_flag) else if (color_change_flag && *color_change_flag != old_changed)
*color_change_flag = theme_preferences_stage.active ? theme_preferences_stage.changed : *color_change_flag; theme_manager_save_preferences ();
g_free (cfg); g_free (cfg);
g_free (path); g_free (path);
@@ -1105,7 +957,7 @@ theme_preferences_create_color_button (GtkWidget *table,
g_object_set_data (G_OBJECT (but), "zoitechat-theme-color-change", color_change_flag); g_object_set_data (G_OBJECT (but), "zoitechat-theme-color-change", color_change_flag);
gtk_grid_attach (GTK_GRID (table), but, col, row, 1, 1); gtk_grid_attach (GTK_GRID (table), but, col, row, 1, 1);
g_signal_connect (G_OBJECT (but), "clicked", G_CALLBACK (theme_preferences_color_cb), parent); g_signal_connect (G_OBJECT (but), "clicked", G_CALLBACK (theme_preferences_color_cb), parent);
if (theme_preferences_staged_get_color (token, &color)) if (theme_get_color (token, &color))
theme_preferences_color_button_apply (but, &color); theme_preferences_color_button_apply (but, &color);
} }
@@ -1280,12 +1132,25 @@ theme_preferences_create_color_page (GtkWindow *parent,
static void static void
theme_preferences_open_gtk3_folder_cb (GtkWidget *button, gpointer user_data) theme_preferences_open_gtk3_folder_cb (GtkWidget *button, gpointer user_data)
{ {
theme_preferences_ui *ui = user_data;
GAppInfo *handler;
char *themes_dir; char *themes_dir;
(void)user_data;
(void)button; (void)button;
themes_dir = zoitechat_gtk3_theme_service_get_user_themes_dir (); themes_dir = zoitechat_gtk3_theme_service_get_user_themes_dir ();
g_mkdir_with_parents (themes_dir, 0700); g_mkdir_with_parents (themes_dir, 0700);
handler = g_app_info_get_default_for_uri_scheme ("file");
if (!handler)
{
theme_preferences_show_message (ui,
GTK_MESSAGE_ERROR,
_("No application is configured to open folders."));
g_free (themes_dir);
return;
}
g_object_unref (handler);
fe_open_url (themes_dir); fe_open_url (themes_dir);
g_free (themes_dir); g_free (themes_dir);
} }
@@ -1540,34 +1405,26 @@ theme_preferences_populate_gtk3 (theme_preferences_ui *ui)
g_ptr_array_unref (themes); g_ptr_array_unref (themes);
} }
static void
theme_preferences_gtk3_import_path (theme_preferences_ui *ui, char *path)
{
char *id = NULL;
GError *error = NULL;
if (!zoitechat_gtk3_theme_service_import (path, &id, &error))
theme_preferences_show_message (ui, GTK_MESSAGE_ERROR,
error ? error->message : _("Failed to import GTK3 theme."));
g_clear_error (&error);
g_free (id);
g_free (path);
theme_preferences_populate_gtk3 (ui);
}
static void static void
theme_preferences_gtk3_import_cb (GtkWidget *button, gpointer user_data) theme_preferences_gtk3_import_cb (GtkWidget *button, gpointer user_data)
{ {
theme_preferences_ui *ui = user_data; theme_preferences_ui *ui = user_data;
GtkFileChooserNative *dialog; GtkWidget *dialog;
GtkFileFilter *filter; GtkFileFilter *filter;
GtkWidget *folder_dialog;
char *path; char *path;
char *id = NULL;
GError *error = NULL;
gint response;
(void)button; (void)button;
dialog = gtk_file_chooser_native_new (_("Import GTK3 Theme"), ui->parent, dialog = gtk_file_chooser_dialog_new (_("Import GTK3 Theme"), ui->parent,
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Import"), _("Import _Folder"), 1,
_("_Cancel")); _("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Import"), GTK_RESPONSE_ACCEPT,
NULL);
theme_manager_attach_window (dialog);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), FALSE); gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), FALSE);
filter = gtk_file_filter_new (); filter = gtk_file_filter_new ();
@@ -1582,15 +1439,43 @@ theme_preferences_gtk3_import_cb (GtkWidget *button, gpointer user_data)
gtk_file_filter_add_pattern (filter, "*.tbz"); gtk_file_filter_add_pattern (filter, "*.tbz");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
if (gtk_native_dialog_run (GTK_NATIVE_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response == 1)
{ {
g_object_unref (dialog); gtk_widget_destroy (dialog);
folder_dialog = gtk_file_chooser_dialog_new (_("Import GTK3 Theme Folder"), ui->parent,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Import"), GTK_RESPONSE_ACCEPT,
NULL);
theme_manager_attach_window (folder_dialog);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (folder_dialog), TRUE);
if (gtk_dialog_run (GTK_DIALOG (folder_dialog)) != GTK_RESPONSE_ACCEPT)
{
gtk_widget_destroy (folder_dialog);
return; return;
} }
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (folder_dialog));
gtk_widget_destroy (folder_dialog);
}
else if (response == GTK_RESPONSE_ACCEPT)
{
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
g_object_unref (dialog); gtk_widget_destroy (dialog);
theme_preferences_gtk3_import_path (ui, path); }
else
{
gtk_widget_destroy (dialog);
return;
}
if (!zoitechat_gtk3_theme_service_import (path, &id, &error))
theme_preferences_show_message (ui, GTK_MESSAGE_ERROR,
error ? error->message : _("Failed to import GTK3 theme."));
g_clear_error (&error);
g_free (path);
theme_preferences_populate_gtk3 (ui);
} }
static void static void

View File

@@ -13,9 +13,5 @@ GtkWidget *theme_preferences_create_color_page (GtkWindow *parent,
struct zoitechatprefs *setup_prefs, struct zoitechatprefs *setup_prefs,
gboolean *color_change_flag); gboolean *color_change_flag);
void theme_preferences_apply_to_session (session_gui *gui, InputStyle *input_style); void theme_preferences_apply_to_session (session_gui *gui, InputStyle *input_style);
void theme_preferences_stage_begin (void);
void theme_preferences_stage_apply (void);
void theme_preferences_stage_commit (void);
void theme_preferences_stage_discard (void);
#endif #endif

View File

@@ -4,7 +4,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#ifdef WIN32 #ifdef WIN32
#include <io.h> #include <io.h>
@@ -277,7 +276,7 @@ theme_runtime_load_migrated_legacy_color (char *cfg,
return palette_read_legacy_color (cfg, mode->legacy_prefix, def->legacy_index, out_color); return palette_read_legacy_color (cfg, mode->legacy_prefix, def->legacy_index, out_color);
} }
static gboolean static void
palette_write_token_color (int fh, const char *mode_name, const ThemePaletteTokenDef *def, const GdkRGBA *color) palette_write_token_color (int fh, const char *mode_name, const ThemePaletteTokenDef *def, const GdkRGBA *color)
{ {
char prefname[256]; char prefname[256];
@@ -285,13 +284,13 @@ palette_write_token_color (int fh, const char *mode_name, const ThemePaletteToke
guint16 green; guint16 green;
guint16 blue; guint16 blue;
g_return_val_if_fail (mode_name != NULL, FALSE); g_return_if_fail (mode_name != NULL);
g_return_val_if_fail (def != NULL, FALSE); g_return_if_fail (def != NULL);
g_return_val_if_fail (color != NULL, FALSE); g_return_if_fail (color != NULL);
g_snprintf (prefname, sizeof prefname, "theme.mode.%s.token.%s", mode_name, def->name); g_snprintf (prefname, sizeof prefname, "theme.mode.%s.token.%s", mode_name, def->name);
theme_palette_color_get_rgb16 (color, &red, &green, &blue); theme_palette_color_get_rgb16 (color, &red, &green, &blue);
return cfg_put_color (fh, red, green, blue, prefname); cfg_put_color (fh, red, green, blue, prefname);
} }
@@ -450,11 +449,12 @@ theme_runtime_load (void)
user_colors_valid = TRUE; user_colors_valid = TRUE;
} }
static gboolean void
theme_runtime_save_to_fd (int fh) theme_runtime_save (void)
{ {
size_t i; size_t i;
size_t j; size_t j;
int fh;
ThemePalettePersistenceMode modes[] = { ThemePalettePersistenceMode modes[] = {
{ "light", "color", &light_palette, &user_colors_valid }, { "light", "color", &light_palette, &user_colors_valid },
{ "dark", "dark_color", &dark_palette, &dark_user_colors_valid }, { "dark", "dark_color", &dark_palette, &dark_user_colors_valid },
@@ -485,8 +485,11 @@ theme_runtime_save_to_fd (int fh)
else else
modes[1].palette = &dark_palette; modes[1].palette = &dark_palette;
if (!cfg_put_int (fh, THEME_PALETTE_MIGRATION_MARKER_VALUE, (char *) THEME_PALETTE_MIGRATION_MARKER_KEY)) fh = zoitechat_open_file ("colors.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
return FALSE; if (fh == -1)
return;
cfg_put_int (fh, THEME_PALETTE_MIGRATION_MARKER_VALUE, (char *) THEME_PALETTE_MIGRATION_MARKER_KEY);
for (i = 0; i < mode_count; i++) for (i = 0; i < mode_count; i++)
{ {
@@ -504,101 +507,11 @@ theme_runtime_save_to_fd (int fh)
if (!custom_tokens[def->token]) if (!custom_tokens[def->token])
continue; continue;
g_assert (theme_palette_get_color (modes[i].palette, def->token, &color)); g_assert (theme_palette_get_color (modes[i].palette, def->token, &color));
if (!palette_write_token_color (fh, modes[i].mode_name, def, &color)) palette_write_token_color (fh, modes[i].mode_name, def, &color);
return FALSE;
} }
} }
return TRUE;
}
gboolean
theme_runtime_save_prepare (char **temp_path)
{
int fh;
char *temp_name;
const char *config_dir;
if (!temp_path)
return FALSE;
config_dir = get_xdir ();
if (!config_dir)
return FALSE;
temp_name = g_build_filename (config_dir, "colors.conf.new.XXXXXX", NULL);
fh = g_mkstemp (temp_name);
if (fh == -1)
{
g_free (temp_name);
return FALSE;
}
if (!theme_runtime_save_to_fd (fh))
{
close (fh); close (fh);
g_unlink (temp_name);
g_free (temp_name);
return FALSE;
}
if (close (fh) == -1)
{
g_unlink (temp_name);
g_free (temp_name);
return FALSE;
}
*temp_path = temp_name;
return TRUE;
}
gboolean
theme_runtime_save_finalize (const char *temp_path)
{
char *config_path;
if (!temp_path)
return FALSE;
config_path = g_build_filename (get_xdir (), "colors.conf", NULL);
#ifdef WIN32
g_unlink (config_path);
#endif
if (g_rename (temp_path, config_path) == -1)
{
g_free (config_path);
return FALSE;
}
g_free (config_path);
return TRUE;
}
void
theme_runtime_save_discard (const char *temp_path)
{
if (!temp_path)
return;
g_unlink (temp_path);
}
gboolean
theme_runtime_save (void)
{
char *temp_path = NULL;
gboolean result;
if (!theme_runtime_save_prepare (&temp_path))
return FALSE;
result = theme_runtime_save_finalize (temp_path);
if (!result)
theme_runtime_save_discard (temp_path);
g_free (temp_path);
return result;
} }
static gboolean static gboolean

View File

@@ -18,10 +18,7 @@ typedef struct
} ThemeGtkPaletteMap; } ThemeGtkPaletteMap;
void theme_runtime_load (void); void theme_runtime_load (void);
gboolean theme_runtime_save (void); void theme_runtime_save (void);
gboolean theme_runtime_save_prepare (char **temp_path);
gboolean theme_runtime_save_finalize (const char *temp_path);
void theme_runtime_save_discard (const char *temp_path);
gboolean theme_runtime_apply_mode (unsigned int mode, gboolean *palette_changed); gboolean theme_runtime_apply_mode (unsigned int mode, gboolean *palette_changed);
gboolean theme_runtime_apply_dark_mode (gboolean enable); gboolean theme_runtime_apply_dark_mode (gboolean enable);
void theme_runtime_user_set_color (ThemeSemanticToken token, const GdkRGBA *col); void theme_runtime_user_set_color (ThemeSemanticToken token, const GdkRGBA *col);

View File

@@ -99,7 +99,7 @@ url_treeview_new (GtkWidget *box)
scroll = gtk_widget_get_parent (view); scroll = gtk_widget_get_parent (view);
gtk_widget_set_hexpand (scroll, TRUE); gtk_widget_set_hexpand (scroll, TRUE);
gtk_widget_set_vexpand (scroll, TRUE); gtk_widget_set_vexpand (scroll, TRUE);
g_signal_connect (G_OBJECT (view), "button-press-event", g_signal_connect (G_OBJECT (view), "button_press_event",
G_CALLBACK (url_treeview_url_clicked_cb), NULL); G_CALLBACK (url_treeview_url_clicked_cb), NULL);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
gtk_widget_show (view); gtk_widget_show (view);

View File

@@ -52,51 +52,6 @@ enum
static void userlist_store_color (GtkListStore *store, GtkTreeIter *iter, ThemeSemanticToken token, gboolean has_token); static void userlist_store_color (GtkListStore *store, GtkTreeIter *iter, ThemeSemanticToken token, gboolean has_token);
static void
userlist_column_width_notify_cb (GtkTreeViewColumn *column, GParamSpec *pspec, gpointer userdata)
{
(void)pspec;
int width = gtk_tree_view_column_get_width (column);
int *target = (int *)userdata;
if (!target || width < 1 || *target == width)
return;
*target = width;
}
static void
userlist_apply_saved_column_width (GtkTreeViewColumn *column, int width)
{
if (!column || width < 1)
return;
gtk_tree_view_column_set_fixed_width (column, width);
}
static void
userlist_update_min_width (session *sess)
{
GtkRequisition minimum;
GtkRequisition natural;
GtkWidget *scrolled_window;
int width;
if (!sess || !sess->gui || !sess->gui->user_box || !sess->gui->namelistinfo || !sess->gui->user_tree)
return;
gtk_widget_get_preferred_size (sess->gui->namelistinfo, &minimum, &natural);
width = MAX (minimum.width, natural.width);
if (width < 1)
width = 1;
scrolled_window = gtk_widget_get_parent (sess->gui->user_tree);
if (GTK_IS_SCROLLED_WINDOW (scrolled_window))
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (scrolled_window), width);
gtk_widget_set_size_request (sess->gui->user_box, width, -1);
}
GdkPixbuf * GdkPixbuf *
get_user_icon (server *serv, struct User *user) get_user_icon (server *serv, struct User *user)
{ {
@@ -155,11 +110,9 @@ fe_userlist_numbers (session *sess)
g_snprintf (tbuf, sizeof (tbuf), _("%d ops, %d total"), sess->ops, sess->total); g_snprintf (tbuf, sizeof (tbuf), _("%d ops, %d total"), sess->ops, sess->total);
tbuf[sizeof (tbuf) - 1] = 0; tbuf[sizeof (tbuf) - 1] = 0;
gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), tbuf); gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), tbuf);
userlist_update_min_width (sess);
} else } else
{ {
gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), NULL); gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), NULL);
userlist_update_min_width (sess);
} }
if (sess->type == SESS_CHANNEL && prefs.hex_gui_win_ucount) if (sess->type == SESS_CHANNEL && prefs.hex_gui_win_ucount)
@@ -709,7 +662,6 @@ static void
userlist_add_columns (GtkTreeView * treeview) userlist_add_columns (GtkTreeView * treeview)
{ {
GtkCellRenderer *renderer; GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
/* icon column */ /* icon column */
renderer = gtk_cell_renderer_pixbuf_new (); renderer = gtk_cell_renderer_pixbuf_new ();
@@ -718,27 +670,15 @@ userlist_add_columns (GtkTreeView * treeview)
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview), gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
-1, NULL, renderer, -1, NULL, renderer,
"pixbuf", 0, NULL); "pixbuf", 0, NULL);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 0);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
/* nick column */ /* nick column */
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
if (prefs.hex_gui_compact) if (prefs.hex_gui_compact)
g_object_set (G_OBJECT (renderer), "ypad", 0, NULL); g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1); gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview), gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
-1, NULL, renderer, -1, NULL, renderer,
"text", 1, THEME_GTK_FOREGROUND_PROPERTY, 4, NULL); "text", 1, THEME_GTK_FOREGROUND_PROPERTY, 4, NULL);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 1);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_min_width (column, 1);
gtk_tree_view_column_set_resizable (column, TRUE);
userlist_apply_saved_column_width (column, prefs.hex_gui_ulist_nick_width);
g_signal_connect (G_OBJECT (column), "notify::width",
G_CALLBACK (userlist_column_width_notify_cb),
&prefs.hex_gui_ulist_nick_width);
if (prefs.hex_gui_ulist_show_hosts) if (prefs.hex_gui_ulist_show_hosts)
{ {
@@ -746,20 +686,10 @@ userlist_add_columns (GtkTreeView * treeview)
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
if (prefs.hex_gui_compact) if (prefs.hex_gui_compact)
g_object_set (G_OBJECT (renderer), "ypad", 0, NULL); g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1); gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview), gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
-1, NULL, renderer, -1, NULL, renderer,
"text", 2, NULL); "text", 2, NULL);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 2);
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_min_width (column, 1);
gtk_tree_view_column_set_resizable (column, TRUE);
userlist_apply_saved_column_width (column, prefs.hex_gui_ulist_host_width);
g_signal_connect (G_OBJECT (column), "notify::width",
G_CALLBACK (userlist_column_width_notify_cb),
&prefs.hex_gui_ulist_host_width);
} }
} }
@@ -886,7 +816,7 @@ userlist_create (GtkWidget *box)
treeview = gtk_tree_view_new (); treeview = gtk_tree_view_new ();
gtk_widget_set_name (treeview, "zoitechat-userlist"); gtk_widget_set_name (treeview, "zoitechat-userlist");
gtk_widget_set_can_focus (treeview, TRUE); gtk_widget_set_can_focus (treeview, TRUE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), TRUE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_selection_set_mode (gtk_tree_view_get_selection gtk_tree_selection_set_mode (gtk_tree_view_get_selection
(GTK_TREE_VIEW (treeview)), (GTK_TREE_VIEW (treeview)),
GTK_SELECTION_MULTIPLE); GTK_SELECTION_MULTIPLE);
@@ -897,26 +827,26 @@ userlist_create (GtkWidget *box)
gtk_drag_source_set (treeview, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_MOVE); gtk_drag_source_set (treeview, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_MOVE);
/* file DND (for DCC) */ /* file DND (for DCC) */
g_signal_connect (G_OBJECT (treeview), "drag-motion", g_signal_connect (G_OBJECT (treeview), "drag_motion",
G_CALLBACK (userlist_dnd_motion), treeview); G_CALLBACK (userlist_dnd_motion), treeview);
g_signal_connect (G_OBJECT (treeview), "drag-leave", g_signal_connect (G_OBJECT (treeview), "drag_leave",
G_CALLBACK (userlist_dnd_leave), 0); G_CALLBACK (userlist_dnd_leave), 0);
g_signal_connect (G_OBJECT (treeview), "drag-data-received", g_signal_connect (G_OBJECT (treeview), "drag_data_received",
G_CALLBACK (userlist_dnd_drop), treeview); G_CALLBACK (userlist_dnd_drop), treeview);
g_signal_connect (G_OBJECT (treeview), "button-press-event", g_signal_connect (G_OBJECT (treeview), "button_press_event",
G_CALLBACK (userlist_click_cb), 0); G_CALLBACK (userlist_click_cb), 0);
g_signal_connect (G_OBJECT (treeview), "key-press-event", g_signal_connect (G_OBJECT (treeview), "key_press_event",
G_CALLBACK (userlist_key_cb), 0); G_CALLBACK (userlist_key_cb), 0);
/* tree/chanview DND */ /* tree/chanview DND */
g_signal_connect (G_OBJECT (treeview), "drag-begin", g_signal_connect (G_OBJECT (treeview), "drag_begin",
G_CALLBACK (mg_drag_begin_cb), NULL); G_CALLBACK (mg_drag_begin_cb), NULL);
g_signal_connect (G_OBJECT (treeview), "drag-drop", g_signal_connect (G_OBJECT (treeview), "drag_drop",
G_CALLBACK (mg_drag_drop_cb), NULL); G_CALLBACK (mg_drag_drop_cb), NULL);
g_signal_connect (G_OBJECT (treeview), "drag-motion", g_signal_connect (G_OBJECT (treeview), "drag_motion",
G_CALLBACK (mg_drag_motion_cb), NULL); G_CALLBACK (mg_drag_motion_cb), NULL);
g_signal_connect (G_OBJECT (treeview), "drag-end", g_signal_connect (G_OBJECT (treeview), "drag_end",
G_CALLBACK (mg_drag_end_cb), NULL); G_CALLBACK (mg_drag_end_cb), NULL);
userlist_add_columns (GTK_TREE_VIEW (treeview)); userlist_add_columns (GTK_TREE_VIEW (treeview));

View File

@@ -581,19 +581,6 @@ fe_exit (void)
g_main_loop_quit(main_loop); g_main_loop_quit(main_loop);
} }
fe_preferences_save_result
fe_preferences_persistence_save_all (void)
{
fe_preferences_save_result result;
result.success = save_config () != 0;
result.partial_failure = FALSE;
result.config_failed = !result.success;
result.theme_failed = FALSE;
return result;
}
void void
fe_new_server (struct server *serv) fe_new_server (struct server *serv)
{ {

View File

@@ -4,6 +4,12 @@
;#define APPARCH "x64" ;#define APPARCH "x64"
;#define PROJECTDIR "C:\...\zoitechat\win32\installer\" ;#define PROJECTDIR "C:\...\zoitechat\win32\installer\"
;http://mitrich.net23.net/?/inno-download-plugin.html
#ifexist "idp.iss"
#define USE_INNO_DOWNLOAD_PLUGIN
#include <idp.iss>
#endif
[Setup] [Setup]
AppName=ZoiteChat AppName=ZoiteChat
AppVersion={#APPVER} AppVersion={#APPVER}
@@ -59,8 +65,8 @@ Name: "plugins\upd"; Description: "Update Checker"; Types: normal custom; Flags:
Name: "plugins\winamp"; Description: "Winamp"; Types: custom; Flags: disablenouninstallwarning Name: "plugins\winamp"; Description: "Winamp"; Types: custom; Flags: disablenouninstallwarning
Name: "langs"; Description: "Language Interfaces"; Types: custom; Flags: disablenouninstallwarning Name: "langs"; Description: "Language Interfaces"; Types: custom; Flags: disablenouninstallwarning
Name: "langs\lua"; Description: "Lua"; Types: normal custom; Flags: disablenouninstallwarning Name: "langs\lua"; Description: "Lua"; Types: normal custom; Flags: disablenouninstallwarning
Name: "langs\perl"; Description: "Perl (requires Perl 5.42)"; Types: custom; Flags: disablenouninstallwarning Name: "langs\perl"; Description: "Perl (requires Perl 5.20)"; Types: custom; Flags: disablenouninstallwarning
Name: "langs\python"; Description: "Python (requires Python 3.14.3)"; Types: custom; Flags: disablenouninstallwarning Name: "langs\python"; Description: "Python (requires Python 3.14.2)"; Types: custom; Flags: disablenouninstallwarning
[Tasks] [Tasks]
Name: portable; Description: "Yes"; GroupDescription: "Portable Mode: Stores configuration files within install directory for portable drives."; Flags: unchecked Name: portable; Description: "Yes"; GroupDescription: "Portable Mode: Stores configuration files within install directory for portable drives."; Flags: unchecked
@@ -276,8 +282,8 @@ begin
begin begin
REDIST := 'https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.16.2/vcredist_2015_x64.exe'; REDIST := 'https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.16.2/vcredist_2015_x64.exe';
PERL := 'https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_54201_64bit/strawberry-perl-5.42.0.1-64bit.msi'; PERL := 'https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.16.2/Perl.5.20.0.x64.msi';
PY3 := 'https://www.python.org/ftp/python/3.14.3/python-3.14.3-amd64.exe'; PY3 := 'https://www.python.org/ftp/python/3.14.2/python-3.14.2-amd64.exe';
SPELL := 'https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.16.2/ZoiteChat.Spelling.Dictionaries.r2.exe'; SPELL := 'https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.16.2/ZoiteChat.Spelling.Dictionaries.r2.exe';
if not CheckVCInstall() then if not CheckVCInstall() then
@@ -288,7 +294,7 @@ begin
if not WizardSilent() then if not WizardSilent() then
begin begin
if IsComponentSelected('langs\perl') and not CheckDLL('perl542.dll') then if IsComponentSelected('langs\perl') and not CheckDLL('perl520.dll') then
begin begin
idpAddFile(PERL, ExpandConstant('{tmp}\perl.msi')) idpAddFile(PERL, ExpandConstant('{tmp}\perl.msi'))
end; end;

View File

@@ -1 +1 @@
2.18.0~pre4 2.18.0~pre3

View File

@@ -6,7 +6,7 @@
<YourDepsPath>c:\gtk-build\gtk</YourDepsPath> <YourDepsPath>c:\gtk-build\gtk</YourDepsPath>
<YourGendefPath>c:\gtk-build\gendef</YourGendefPath> <YourGendefPath>c:\gtk-build\gendef</YourGendefPath>
<YourPerlPath>c:\gtk-build\perl-5.42.0.1</YourPerlPath> <YourPerlPath>c:\gtk-build\perl-5.20</YourPerlPath>
<YourPython3Path>c:\gtk-build\python-3.14</YourPython3Path> <YourPython3Path>c:\gtk-build\python-3.14</YourPython3Path>
<YourWinSparklePath>c:\gtk-build\WinSparkle</YourWinSparklePath> <YourWinSparklePath>c:\gtk-build\WinSparkle</YourWinSparklePath>
@@ -24,7 +24,7 @@
<GendefPath>$(YourGendefPath)</GendefPath> <GendefPath>$(YourGendefPath)</GendefPath>
<WinSparklePath>$(YourWinSparklePath)\$(ZoiteChatPlatform)</WinSparklePath> <WinSparklePath>$(YourWinSparklePath)\$(ZoiteChatPlatform)</WinSparklePath>
<PerlPath>$(YourPerlPath)\$(ZoiteChatPlatform)</PerlPath> <PerlPath>$(YourPerlPath)\$(ZoiteChatPlatform)</PerlPath>
<PerlLib>perl542</PerlLib> <PerlLib>perl520</PerlLib>
<Python3Path>$(YourPython3Path)\$(ZoiteChatPlatform)</Python3Path> <Python3Path>$(YourPython3Path)\$(ZoiteChatPlatform)</Python3Path>
<Python3Lib>python314</Python3Lib> <Python3Lib>python314</Python3Lib>