103 Commits

Author SHA1 Message Date
69985913b8 win32 argv: stop trusting GLib, add “zoitechat” lifesaver 2026-02-26 13:35:09 -07:00
df45cc996d Fix Windows theme imports with uppercase .TAR.GZ/etc (case-insensitive archive check) 2026-02-26 13:15:49 -07:00
5763653672 I fixed a Windows theming regression path in fe_apply_windows_theme() by changing the fallback-disable condition from “a GTK3 theme name is configured” to “a GTK3 theme provider is actually active.” This ensures fallback dark/light palette CSS is still applied when a configured imported GTK3 theme fails to load, preserving Windows release theming behavior instead of leaving mismatched visuals.
I added an in-code explanation documenting this Windows-release safety behavior so the intent is explicit for future maintenance.
2026-02-26 12:10:59 -07:00
2ece544792 Updated the Windows Inno Setup installer template to explicitly show the install-directory step by setting DisableDirPage=no, so users are asked where to install ZoiteChat.
Disabled automatic reuse of a previously selected install path by setting UsePreviousAppDir=no, ensuring the prompt appears each installer run.
2026-02-26 11:56:01 -07:00
8e0958fd19 Added a Windows-specific startup path in main() to reconstruct argc/argv from g_win32_get_command_line() before any argument parsing, so GLib option parsing no longer depends on potentially malformed CRT argv in subsystem/protocol-handler launches (a likely source of your launch crash stack through glib-2.0-0.dll).
Ensured the allocated Windows command-line vector is freed on all early-return and normal-exit paths in main() to avoid leaks/regressions from the new startup handling.
2026-02-26 11:54:42 -07:00
324aeab8c9 Fixed the Win32 startup path initialization in fe_args to avoid blindly calling g_path_get_dirname(argv[0]) when argv may be missing/invalid in subsystem:windows launch contexts (like URL handler launches).
Updated logic to prefer g_win32_get_package_installation_directory_of_module(NULL) first, and only fall back to argv[0] when argc > 0, argv != NULL, and argv[0] != NULL, preventing null/invalid pointer access during startup.
2026-02-26 11:38:08 -07:00
e8dbe06f01 Added a Win32-only forward declaration for fe_apply_windows_theme(gboolean dark) before its first use so MSVC sees the correct signature and no longer infers an int return type. This addresses the C4013 + C2371 sequence from your build log. 2026-02-26 11:10:33 -07:00
f3213c56eb I implemented a broader, platform-agnostic theme application path so chat-area surfaces and controls actually follow the selected ZoiteChat dark/light mode, instead of relying on a narrow fallback path. This adds a dedicated app CSS provider (theme_surface_provider) and applies palette-based foreground/background rules for core widgets (box, grid, frame, viewport, paned, notebook, eventbox, scrolledwindow, treeview, button, entry) scoped by .zoitechat-light / .zoitechat-dark.
I wired that CSS application into the theme switch flow (fe_apply_theme_for_mode) so changing theme mode now reapplies those surface colors immediately during runtime mode changes.
2026-02-26 11:03:18 -07:00
9ef607f44a Fixed GTK3 theme switching on Win32 so fallback window CSS is synchronized immediately when switching back to the system theme (theme_name == NULL) by calling fe_apply_windows_theme(dark) in that path before provider cleanup.
Fixed GTK3 theme activation on Win32 so fallback window CSS is disabled immediately after loading an imported GTK3 theme, preventing mixed styling (like unthemed buttons/chat areas) during runtime theme changes
2026-02-26 08:58:38 -07:00
a93bed2c41 Adjusted the Windows theme fallback path so it does not apply ZoiteChat’s fallback window-color CSS when a GTK3 theme is selected, preventing the mixed-theme effect you reported (e.g., mismatched button/chat window colors).
Added cleanup for previously-added fallback CSS providers (with widget style reset) when a GTK3 theme is active, so the imported theme can fully control styling consistently.
Kept the original Windows fallback CSS behavior for cases where no imported GTK3 theme is set, so non-GTK3-theme behavior remains unchanged.
2026-02-26 08:41:52 -07:00
d10c9654fa Added a GTK3 theme directory resolver that supports versioned theme folders (gtk-3.x) and selects the best match for the running GTK minor version, instead of assuming only gtk-3.0. This improves compatibility with real-world GTK3 themes that split selectors/styles by GTK minor versions.
Updated theme application to load CSS/resources from the resolved gtk-3.x folder and updated the error path/message when a valid gtk-3.x/gtk.css layout is missing.

Exposed the resolver in the GTK frontend header so other GTK UI code can validate theme layouts consistently.

Updated the Preferences GTK3 theme picker to validate themes via the resolver (so themes with e.g. gtk-3.24/gtk.css now appear as valid).

Updated archive import validation to recognize gtk-3.x directories (not just gtk-3.0) and adjusted user-facing validation messages accordingly.
2026-02-26 08:35:37 -07:00
a823047104 Fixed imported GTK3 theme precedence so theme CSS can override ZoiteChat app-level CSS (including button background rules) by changing the provider priority from GTK_STYLE_PROVIDER_PRIORITY_APPLICATION to GTK_STYLE_PROVIDER_PRIORITY_USER.
Updated the inline comment to document why user-level priority is needed for correct themed button styling behavior.
2026-02-26 08:26:03 -07:00
bf349a27b1 Updated GTK3 theme provider registration to use GTK_STYLE_PROVIDER_PRIORITY_APPLICATION (instead of GTK_STYLE_PROVIDER_PRIORITY_THEME) when applying imported themes, so the selected GTK3 theme consistently overrides the system theme for ZoiteChat widgets.
Added an inline code comment explaining the priority choice and the consistency intent.
2026-02-26 08:21:15 -07:00
90ada474a0 Added GTK3 theme resource lifecycle management so ZoiteChat now unregisters prior theme resources and can register a theme’s gtk.gresource bundle when available (gtk-3.0/gtk.gresource). This improves compatibility with full GTK3 themes that depend on bundled resource URIs, not just plain CSS files.
Extended fe_apply_gtk3_theme_with_reload to:

detect gtk.gresource,

register it before applying CSS,

unregister resources when no resource file is present or when switching back to system theme,

and clean up allocated paths consistently on error paths
2026-02-26 08:04:27 -07:00
4a996c9135 Added a reload-capable GTK3 theme apply API (fe_apply_gtk3_theme_with_reload) and kept fe_apply_gtk3_theme as the default fast-path wrapper (force_reload = FALSE).
Updated the same-theme early return so it is bypassed when reload is requested, while preserving the existing provider reset/replacement flow, gtk_style_context_reset_widgets, and top-level reapply behavior.

Wired setup import/apply flow to force a reload on the next apply after successful archive import, ensuring same-name imported themes are reloaded from disk; the flag is cleared after apply and when switching back to system theme.
2026-02-26 02:38:12 -07:00
c9682d98f3 Updated setup_theme_gtk3_import_cb so the GTK3 theme import file chooser dialog now calls fe_apply_theme_to_toplevel(dialog) immediately after gtk_file_chooser_dialog_new, ensuring it receives app-level theme classes like other dialogs.
Added the same short explanatory comment style already used in setup_theme_show_message (“Window classes are required for GTK CSS selectors like .zoitechat-dark / .zoitechat-light.”), keeping behavior/style aligned with existing code conventions.

    Verified the open/cancel/import flow is unchanged: the same GTK_RESPONSE_ACCEPT gate, early return on cancel, file extraction path retrieval, and import success/error handling remain intact.
2026-02-26 02:33:52 -07:00
8a4ecf8649 Fixed the GTK3 theme persistence bug in Preferences by syncing the in-dialog working copy (setup_prefs.hex_gui_gtk3_theme_name) whenever a GTK3 theme is applied, so pressing OK no longer overwrites the newly selected theme with stale state.
Fixed the same persistence path for “Use System GTK Theme” by clearing both prefs and setup_prefs, preventing the theme from reverting after the dialog closes.

    Reverted GTK3 provider priority back to GTK_STYLE_PROVIDER_PRIORITY_THEME (from application priority), which addresses the dropdown/menu rendering regression introduced by the previous commit.
2026-02-26 02:30:34 -07:00
252f4a3c07 Fixed GTK3 theme teardown to force a full widget style refresh after removing ZoiteChat’s GTK3 theme provider, so switching back to system theme updates existing windows/widgets immediately.
Changed imported GTK3 theme provider registration from GTK_STYLE_PROVIDER_PRIORITY_APPLICATION to GTK_STYLE_PROVIDER_PRIORITY_THEME, so GTK3 theme rules apply correctly across themed controls (including menu/dropdown-related GTK theme elements) instead of being overly overridden by app-priority styling.
2026-02-26 02:22:00 -07:00
d21a5c1b60 Removed the legacy .hct/.zct theme-path behavior and made theme argument detection GTK3-archive-only (.zip, .tar, .tar.gz, .tgz, .tar.xz, .txz).
Deleted the old ZoiteChat palette/event theme import/apply implementation and kept GTK3 archive import as the sole theme import backend; the GTK3 import API now optionally returns the imported theme name for better caller messaging.

Updated startup and /URL handling so theme archives are imported into gtk3-themes and users are prompted to apply them via Theme settings, instead of auto-applying old ZoiteChat themes.

Simplified the Theme Manager UI/data model to GTK3-only by removing the old “ZoiteChat Theme” controls and keeping the GTK3 import/apply/use-system workflow.
2026-02-26 02:18:22 -07:00
a1ba30865a Kept legacy .zct/.hct import flow untouched while improving GTK3 archive validation logic: GTK3 import now explicitly distinguishes between archives that include gtk-3.0 but miss gtk.css, versus archives that are not GTK3 theme layouts at all. This is implemented in the GTK3 archive scan/import path only (zoitechat_find_gtk3_theme_root + zoitechat_import_gtk3_theme_archive). 2026-02-26 01:01:09 -07:00
607faa80ca Fixed the GTK3 dropdown regression by switching from combo-box ID/path behavior to an explicit internal index→full-path mapping (gtk3_theme_paths) while keeping user-facing theme names in the dropdown text. This preserves internal full path mapping without relying on active-id lookups.
Kept GTK3 discovery restricted to the app-local install directory (get_xdir()/gtk3-themes) and only included directories containing gtk-3.0/gtk.css.

Ensured theme selection is restored/saved correctly by matching saved pref name against discovered entries and applying via the selected internal path, then persisting prefs.hex_gui_gtk3_theme_name with save_config().

Preserved/updated empty-invalid status behavior to show “No valid GTK3 themes found.” when no usable themes exist (or saved selection is invalid).

Added proper cleanup for the new internal mapping via setup_theme_ui_free and wired it into g_object_set_data_full.
2026-02-26 00:56:17 -07:00
1c1110847c Fixed the GTK3 theme dropdown population to include all expected sources again (ZoiteChat local store, user local themes, and system theme dirs), which resolves the “messed up selector” behavior from the previous change.
Restored proper initial selection logic so the dropdown now prefers saved gui_gtk3_theme_name when present, and otherwise falls back to the current GTK gtk-theme-name.

    Fixed selection UX by not forcing index 0; it starts unselected and selects only if a real match is found. Also made Apply button sensitivity follow actual selection state.

    Updated the status text to reflect mixed-source theme discovery and added cleanup for allocated selection strings/path entries in this code path.
2026-02-26 00:47:04 -07:00
a796f78884 Fixed the GTK3 theme import crash by replacing the dark-variant notification call from the signal macro path to fe_message(..., FE_MSG_INFO), avoiding the segfaulting path during import completion while preserving user feedback. 2026-02-26 00:35:42 -07:00
4354aaa57a Added a new backend API, zoitechat_import_gtk3_theme_archive(const char *archive_path, GError **error), and exposed it in the common header so GTK setup code can call a shared import path instead of inlining extraction logic.
Updated the GTK3 import callback in setup.c to:

    open a file chooser titled Import GTK3 Theme ZIP,

    enforce a ZIP-focused chooser filter (*.zip, *.ZIP),

    call the new backend function,

    show success/failure dialogs through setup_theme_show_message,

    refresh the GTK3 theme list immediately after successful import.

Updated the GTK3 section button label to Import GTK3 Theme ZIP and added/used new translatable strings for the new button text and import messages.
2026-02-26 00:16:05 -07:00
4aeb5b5697 Split the theme setup page into two explicit framed sections: “ZoiteChat Theme” (legacy colors.conf / pevents.conf flow) and “GTK3 Theme” (GTK theme import/select/apply flow), with distinct button labels like “Apply ZoiteChat Theme” and “Apply GTK3 Theme.”
Expanded setup_theme_ui to track separate widget state for ZoiteChat controls and GTK3 controls (zoitechat_* and gtk3_* fields), so the two flows are no longer sharing ambiguous UI pointers.

    Kept the existing ZoiteChat apply path using zoitechat_apply_theme, but updated selection/status/apply messaging so it clearly indicates palette/event updates rather than GTK theme activation.

    Added GTK3 theme management behavior:

        discovery/population from standard theme directories,

        import from archive via file chooser into ~/.themes/<basename>,

        apply via GtkSettings (gtk-theme-name),

        status/info messages that explicitly say GTK3 activation does not change ZoiteChat palette settings.
2026-02-26 00:11:05 -07:00
30609ba6db Updated Win32 theme CSS generation in fe_apply_windows_theme to build .zoitechat-dark and .zoitechat-light styles dynamically from palette values (COL_FG/COL_BG) instead of fixed hex literals, via a new helper that serializes PaletteColor with gdk_rgba_to_string.
Kept native titlebar dark-mode behavior intact by leaving the existing Win32 titlebar flow untouched and continuing to call theme preference updates in fe_apply_windows_theme.
Ensured theme/palette apply paths refresh CSS by routing both FE_GUI_APPLY and setup theme apply through fe_apply_theme_for_mode(...), which re-runs Win32 CSS application and re-applies classes to toplevel windows.
2026-02-25 23:53:31 -07:00
6b8e41b4c6 Updated mg_create_tabmenu to remove the hardcoded inline foreground="#3344cc" color from the top menu title and keep only bold emphasis (<b>…</b>), so GTK theme colors are used naturally. 2026-02-25 23:47:42 -07:00
0edab77fac Removed the local menu_icon_exists_in_resource probe from menu.c, so this file no longer carries a hardcoded /icons/menu/light resource check path. menu_icon_widget_new now calls gtkutil_menu_icon_exists for the zc-menu-* candidate check. This keeps the same fallback flow for custom icons: direct readable path first, then config-dir path, then stock/themed lookup.
Added gtkutil_menu_icon_exists to gtkutil.c and declared it in gtkutil.h. The implementation uses a shared helper that resolves menu icon resources with theme-variant-aware lookup (variant first, then light fallback) for both png and svg, so probing behavior now lives in the same subsystem as gtkutil_image_new_from_stock.
2026-02-25 23:40:38 -07:00
c8ae4f3b18 Removed the unused gtkutil_menu_icon_pixbuf_new helper from src/fe-gtk/gtkutil.c (it no longer appears between the surrounding menu icon helper and stock-icon mapping functions).
Kept gtkutil_menu_icon_image_new as the single menu-icon loading path, which already contains the requested theme variant selection and light-variant fallback behavior for both PNG and SVG assets.
2026-02-25 23:36:01 -07:00
578a417804 Added theming to menu_about() immediately after gtk_about_dialog_new() by calling fe_apply_theme_to_toplevel (GTK_WIDGET (dialog));, with the requested short CSS-selector comment style.
Added theming to setup_browsefont_cb() immediately after gtk_font_chooser_dialog_new(...) by calling fe_apply_theme_to_toplevel (dialog);, plus the same short comment for consistency/discoverability.
Added theming to setup_color_cb() immediately after gtk_color_chooser_dialog_new(...) by calling fe_apply_theme_to_toplevel (dialog);, again with the matching comment.
2026-02-25 23:30:35 -07:00
440e9ecf5a Updated fe_ctrl_gui()’s FE_GUI_APPLY branch to match the Preferences → Theme apply sequence by loading palette data first, then re-applying current dark-mode state, and only then calling setup_apply_real(TRUE, TRUE, TRUE, FALSE);.
Added an inline regression-prevention comment noting this path should stay in parity with setup_theme_apply_cb.

    Verified palette.h is already included in src/fe-gtk/fe-gtk.c (no include changes required).
2026-02-25 23:27:21 -07:00
ac2ab1443c Added fe_apply_theme_to_toplevel() for:
Standard GTK file chooser fallback dialog in src/fe-gtk/gtkutil.c

        Font chooser dialog in src/fe-gtk/setup.c

        Color chooser dialog in src/fe-gtk/setup.c

        About dialog in src/fe-gtk/menu.c
2026-02-25 23:18:19 -07:00
ce5128e4fb Added a theme_name null guard in the Adwaita/Yaru workaround condition inside create_input_style() so g_str_has_prefix() is only called when theme_name is non-null, while preserving existing behavior for non-null theme names.
Left allocation/free flow unchanged; theme_name is still freed exactly once at the existing cleanup point after the reload block.
2026-02-25 22:52:40 -07:00
c37faa1492 Refactored the Preferences color-page edit-source model to use an explicit snapshot pointer (setup_color_edit_source_colors) and a helper that selects light vs dark snapshot palettes, so the page preview is decoupled from the runtime colors[] palette. This affects selector refresh, page initialization, and cleanup lifecycle.
Updated edit-target and dark-mode combo callbacks on the color page to stop applying global palette mode directly; they now only switch/refresh the Preferences page source palette.
Changed color-chooser behavior so setup_color_response_cb() writes edits to the selected target snapshot via palette_user_set_color / palette_dark_set_color, then refreshes only page widgets (no runtime palette apply). Also updated dialog initialization to read from the current edit-source snapshot.
Added palette snapshot accessors (palette_user_colors, palette_dark_colors) in the palette API and implementation so Preferences can render from light/dark snapshots safely without mutating runtime palette state.
Runtime palette changes remain on the real apply paths (theme/dark-mode application), not edit-target toggles.
2026-02-25 22:48:55 -07:00
685989fa25 Updated fe_system_prefers_dark() to remove the old !has_theme_name gate and always read gtk-application-prefer-dark-theme whenever that property exists. Theme-name matching is still kept as an additional signal.
Added deterministic dark-mode precedence by combining explicit signals (theme_name_prefers_dark || property_prefers_dark), while preserving Windows system preference as another dark-enabling signal when available. This ensures “dark if any explicit dark signal is true.”
Re-checked the relevant callers (fe_auto_dark_mode_changed() and fe_apply_theme_for_mode()): they consume fe_system_prefers_dark() output and do not depend on the removed !has_theme_name conditional behavior.
2026-02-25 22:42:43 -07:00
cbc474477b Updated gtkutil_menu_icon_theme_variant() to select the menu icon theme variant from the app’s effective dark-mode state first (fe_dark_mode_state_is_initialized() + fe_dark_mode_is_enabled()), and only use GTK/theme-name heuristics as fallback before app state is initialized. This preserves the existing light-asset fallback behavior in menu icon loading logic.
Added a new frontend helper declaration fe_dark_mode_state_is_initialized() in the GTK frontend header so callers can check whether dark-mode state is ready.
Implemented dark-mode initialization tracking in fe-gtk.c via a new static flag, set when auto mode state is externally set and during fe_init(), and exposed it through fe_dark_mode_state_is_initialized().
2026-02-25 22:31:52 -07:00
51f8795d1a Updated create_input_style() so input selection CSS now prefers palette-derived COL_MARK_FG / COL_MARK_BG colors directly (as #RRGGBB from sel_* values), instead of defaulting to @theme_selected_*.
Added a guarded fallback path that only uses theme lookup/string conversion when palette selection components are invalid (isfinite checks fail), with palette values as secondary fallback there too. This keeps theme colors out of the primary path while preserving robustness for malformed data.
Kept needs_reload dependent on last_sel_* tracking, so changing selection colors in Preferences still triggers immediate CSS regeneration (including across light/dark mode).
2026-02-25 22:25:35 -07:00
faacd95dfc Added setup-local state for palette editing target (setup_color_edit_dark_palette) plus Light/Dark option strings, so palette editing is no longer coupled to runtime AUTO dark-mode detection. This keeps the choice in Preferences state only.
Added a new Editing: combo control near the dark-mode selector in setup_create_color_page, with a callback that switches between Light/Dark palette targets and refreshes swatches immediately using the same refresh path as dark-mode UI updates.
    Updated the dark-mode combo callback to refresh color swatches based on the explicit editing target (not runtime dark-mode detection), preserving existing runtime theme behavior while editing persisted overrides.
    Updated setup_color_response_cb to write color changes to palette_dark_set_color vs palette_user_set_color based on the new edit-target state.
    Initialized the editing target in setup_create_color_page from explicit Dark mode selection only (hex_gui_dark_mode == ZOITECHAT_DARK_MODE_DARK), avoiding AUTO runtime detection for editing context.
2026-02-25 21:28:08 -07:00
ed02b21228 Extended setup_dark_mode_menu_cb so after setup_menu_cb it now computes the selected dark-mode state via fe_dark_mode_is_enabled_for(setup_prefs.hex_gui_dark_mode), swaps the in-memory editor palette with palette_apply_dark_mode(...), and immediately refreshes color swatches. This keeps the editor model synchronized with the dark-mode combo selection.
Added setup_refresh_color_selector_widgets() to iterate color_selector_widgets, resolve each button’s stored color index, and re-run setup_color_button_apply against colors[] so all selectors repaint to the active palette.
    Updated setup_create_color_button to register each widget’s palette index (zoitechat-color-index), enabling correct per-button repaint during mode switches.
    Preserved existing persistence behavior in setup_color_response_cb (palette_dark_set_color vs palette_user_set_color) so changes remain non-destructive until existing OK/Save flow persists them.
2026-02-25 21:22:56 -07:00
d321717da8 Hardened create_input_style() so selection-color CSS no longer hard-depends on @theme_selected_*: it now first tries symbolic theme colors via gtk_style_context_lookup_color(), and only falls back when unavailable.
Added a fallback path that derives selection colors from palette values (COL_MARK_FG/COL_MARK_BG) and then samples selected-state colors from a GTK style context when possible, emitting explicit color strings for CSS.
Ensured fallback regeneration is tied to the same reload flow by extending needs_reload tracking with selection palette channels and persisting those last-seen values.
Kept Preferences > Colors foreground/background behavior intact for normal input rendering; only selection-specific CSS is conditionally overridden. Base text/background/caret rules remain unchanged while only text selection uses the new selection logic.
2026-02-25 20:59:07 -07:00
6310ab245c Updated fe_apply_theme_for_mode() to immediately reapply fe_apply_theme_to_toplevel() across all currently-open GTK toplevel windows (gtk_window_list_toplevels()), so mode switches update existing windows without reopening them.
Added/kept lifecycle call sites for main and detached/channel windows, with comments explaining that .zoitechat-dark / .zoitechat-light classes are required for GTK CSS selectors. This includes top/tab windows and server list/edit windows.
Wired dialog/toplevel creation paths in src/fe-gtk/ to call fe_apply_theme_to_toplevel() (without duplicating platform logic), including common prompt/message dialogs and feature-specific dialogs (join, notify, setup, ignore/ban, etc.), each with the requested brief comment near the new call site.
2026-02-25 20:39:48 -07:00
5952006662 Refactored fe_system_prefers_dark() to always allow gtk-application-prefer-dark-theme to be read as a fallback (when no explicit theme name is set), removing the previous suppression tied to app-written state. This preserves priority for explicit dark theme names and platform-native preference checks before the GTK property fallback.
Added a short in-code comment explaining why app-written GTK property state must not permanently block future reads in AUTO mode.
Removed the now-unneeded app_set_prefer_dark tracking behavior from fe_set_gtk_prefer_dark_theme(), so writes no longer disable later fallback reads.
Confirmed fe_auto_dark_mode_changed() still prevents reapply loops by early-returning when enabled == auto_dark_mode_enabled before calling theme/apply logic.
2026-02-25 20:32:44 -07:00
e4cb453915 Added a centralized theme-class application in gtkutil_window_new() so any toplevel created through this helper gets fe_apply_theme_to_toplevel() during construction. This covers most non-session windows consistently at creation time.
Updated Preferences window creation to explicitly apply the toplevel theme after gtk_widget_show_all() in setup_window_open(), matching your requested timing there.
Added explicit theme application for non-session windows that bypass gtkutil_window_new() and use direct gtk_window_new() in server list UI (editserv and servlist).
Extended mg_apply_setup() to iterate all current GTK toplevels (gtk_window_list_toplevels()) and reapply fe_apply_theme_to_toplevel() during setup/theme reapply flows, ensuring existing windows stay consistent after theme changes. Palette override widgets were not touched.
2026-02-25 20:27:15 -07:00
361e35de7f Updated chanview_apply_theme() in src/fe-gtk/chanview.c to apply the palette colors unconditionally (for tree view chanview), instead of branching on raw dark-mode enum checks. This keys behavior off the already-resolved palette output, which matches how setup_apply_to_sess() / palette_apply_dark_mode() flows are intended to work.
Preserved font handling exactly as before (input_style->font_desc when available).
Added inline rationale comment clarifying that AUTO/light should continue using palette-managed colors and should not revert to GTK theme defaults in a way that clears custom colors.
2026-02-25 20:23:01 -07:00
bbde2e5578 Added a new internal state flag, app_set_prefer_dark, and now set it whenever fe_set_gtk_prefer_dark_theme() writes gtk-application-prefer-dark-theme, so AUTO detection can distinguish app-authored writes from system/user signals.
Reworked fe_system_prefers_dark() to prioritize non-app-written sources in AUTO flow:

        first: gtk-theme-name dark-variant heuristic,

        then (Windows): native platform detection via fe_win32_try_get_system_dark,

        only then fallback to gtk-application-prefer-dark-theme when no theme-name signal was available and the app has not written that property.

    Kept manual LIGHT/DARK behavior unchanged by preserving the existing mode application path (fe_apply_theme_for_mode() still drives fe_set_gtk_prefer_dark_theme() directly).

    Verified fe_auto_dark_mode_changed() and fe_init() signal wiring still trigger AUTO palette/theme refreshes on system theme changes (notify::gtk-theme-name and existing notify callback flow remain in place).
2026-02-25 20:03:20 -07:00
97c6f36b20 Adjusted create_input_style so it no longer globally forces color on #zoitechat-inputbox, reducing over-constraining while still applying the user-selected background and caret color where intended. This keeps non-text-node state rendering more theme-driven.
Kept user override support for baseline text color and caret color on the input’s text node (#zoitechat-inputbox text).
Added targeted state-aware text rules for :focus and :backdrop (to preserve readability when theme state styling changes), plus a softened :disabled text rule instead of broad global color forcing.
Added explicit selection-node handling (#zoitechat-inputbox text selection) using theme selection tokens so selected text remains readable and aligned with Adwaita/Yaru-style theme behavior.
Preserved the existing Adwaita/Yaru background-image workaround logic, so fallback behavior remains compatible with those themes.
2026-02-25 19:43:19 -07:00
deepend-tildeclub
2bf32fc770 Merge pull request #90 from ZoiteChat/code-cleanup
Code cleanup
2026-02-25 18:16:54 -07:00
3e095c3c33 Removed two redundant inline comments in the file dialog response/done handlers, leaving the behavior unchanged and the control flow cleaner.
Removed an old commented-out helper function block (gtkutil_treeview_get_selected_iter) that was dead/commented code.
2026-02-25 18:07:26 -07:00
3445d946bc Removed a redundant inline comment in icon loading/scaling logic, leaving behavior unchanged.
Removed a redundant inline comment in the Windows sysinfo volume-name guard path, with no functional impact.
Removed a redundant inline comment in WinRT toast setup while keeping the same notification/audio attribute behavior.
2026-02-25 18:05:21 -07:00
7578928199 Cleaned up redundant/outdated inline comments in the text frontend argument/config and GUI control paths while leaving behavior unchanged (comment-only cleanup). 2026-02-25 16:22:46 -07:00
deepend-tildeclub
428127ef40 Merge pull request #91 from ZoiteChat/fix-application-focus
Added a Windows-only helper (mg_win32_allow_autohide_taskbar) that ge…
2026-02-25 16:20:47 -07:00
e3f932aa6b Updated the Win32 window-state handling to include shellapi.h and query taskbar auto-hide/taskbar edge state via SHAppBarMessage, so maximized windows can leave a 1px reveal edge for the auto-hidden taskbar.
Added monitor-aware work-area adjustment when maximized (MonitorFromWindow + GetMonitorInfo) and shrink by 1px on the detected taskbar edge (including bottom edge), then apply that rectangle with SetWindowPos. This addresses the “mouse at bottom edge should unhide taskbar” behavior.
Kept the existing HWND_NOTOPMOST safeguard in place after the adjustment, preserving prior not-topmost behavior.
2026-02-25 14:48:18 -07:00
7cfa3b3513 Added a Windows-only helper (mg_win32_allow_autohide_taskbar) that gets the native HWND and calls SetWindowPos(..., HWND_NOTOPMOST, ...) for non-fullscreen window-state transitions, so a maximized ZoiteChat window no longer blocks the taskbar auto-hide reveal edge.
Hooked that helper into mg_windowstate_cb so it runs whenever the main window state changes (while preserving existing maximize/fullscreen preference handling).
2026-02-25 14:18:23 -07:00
81c691491c Removed three redundant inline comments in joind_ok_cb that duplicated obvious control flow, leaving behavior unchanged and improving readability. 2026-02-25 13:55:44 -07:00
c361602b1a Removed four unneeded section comments in src/common/notify.h (WATCH/MONITOR/general/old ISON labels), leaving only the function declarations for a cleaner header interface. 2026-02-25 13:51:22 -07:00
99b969067e Removed one stale, commented-out debug/error line in the PCI device-name lookup path (pci_find_fullname), leaving behavior unchanged and making the function cleaner. 2026-02-25 13:29:20 -07:00
6e8b750c68 Removed an obsolete commented-out hdiutil line from the macOS bundling script, leaving only the active packaging path (zip) to keep the script cleaner and easier to scan. 2026-02-25 13:04:05 -07:00
df37b44cc8 Cleaned up unneeded comment noise in the Solus eopkg workflow by replacing an 11-line explanatory block with a concise 2-line comment while preserving the key rationale for --ignore-file-conflicts and required Meson tooling install. 2026-02-25 13:01:21 -07:00
9548be0cec Removed redundant inline comments in the Winamp plugin by simplifying the plugin handle declaration and cleanup comments around initialization/return values, while keeping functional comments intact.
Removed the redundant return 1 inline comment in the Exec plugin init function.
2026-02-25 12:57:42 -07:00
deepend-tildeclub
588e27b456 Remove Debian Build badge from README
Removed Debian Build badge from README.
2026-02-25 10:32:21 -07:00
deepend-tildeclub
7032d0c6b7 Update contact email in appdata XML file 2026-02-25 10:23:59 -07:00
deepend-tildeclub
72e9a99315 Update developer information and homepage URL 2026-02-25 10:17:14 -07:00
3cff6742f5 Removed unneeded inline comments around the Win32 error-formatting fallback in errorstring() and simplified matching block-closing lines, without changing behavior. 2026-02-25 02:37:08 -07:00
6a02f578b6 Removed obsolete commented-out lines from fe_cleanup() so the function no longer contains dead commented code.
Removed an unnecessary explanatory comment above the unconditional early return in log_handler(), leaving only the active behavior.

Removed an unneeded section marker comment before fe_idle() to keep surrounding code cleaner.
2026-02-25 02:34:50 -07:00
e62769b361 Cleaned up unneeded comments in DCC receive/connect code by removing:
a stale commented-out ACK block in the DCC receive error path,

    an unnecessary speculative note before the quoted filename handling,

    and an editorial inline comment on a static variable declaration.
2026-02-25 02:30:46 -07:00
9df9776238 Removed a stale multi-line # TODO note block from the common Meson build file to clean up unneeded comments without changing build logic.
Removed an old commented-out /* FIXME ... */ prototype block from servlist.h, leaving only active declarations.
2026-02-25 02:28:10 -07:00
4beabb6bf5 Removed a stale commented-out debug function block from the fishlim plugin source to reduce dead/commented code.
Removed the corresponding commented-out RAW LINE hook entry so only active handlers remain in plugin initialization.
2026-02-25 02:24:11 -07:00
10d5bb91ab Cleaned up unneeded, commented-out debug logging lines in Perl plugin callback handlers (server_cb, command_cb, and print_cb) without changing runtime behavior. 2026-02-25 02:14:38 -07:00
7c9c615aed Removed redundant inline comments from the fishlim IRC parsing helpers where the comments only repeated obvious code behavior, while preserving all function docblocks and logic. 2026-02-25 02:12:10 -07:00
fd48c97209 Removed four redundant inline comments in src/fe-gtk/urlgrab.c to clean up readability without changing behavior (treeview enum declaration area, right-click selection block, headers visibility call, and URL list overflow trimming block). 2026-02-25 02:09:35 -07:00
e58bf2be22 Cleaned up redundant comments in dcc_listen_init by removing obvious/explanatory noise and an obsolete commented-out debug printf, while leaving logic unchanged. 2026-02-25 02:07:38 -07:00
dc6453e230 Removed redundant inline comments in lastact_update and lastact_getfirst where the code was already self-explanatory, without changing behavior.
Simplified away_check by removing comment clutter and keeping only the logic flow, including the WHO batching behavior.
Removed unneeded commentary around lag-check helpers and timer reinitialization to keep the core timer code cleaner and easier to scan.
2026-02-25 02:04:31 -07:00
b3a0288fd9 Cleaned up stale inline comments in the tab scrolling handlers by removing outdated explanatory text while keeping behavior unchanged (tab_left_is_moving / tab_right_is_moving reset paths).
Removed an old commented-out gtk_container_set_border_width(...) line that was dead/commented code in cv_tabs_init.
Simplified the tab-switch condition by removing a legacy commented expression from if (is_switching).
2026-02-25 02:01:11 -07:00
9c86f18982 Cleaned up unneeded inline comments in plugins/python/python.py while keeping runtime behavior unchanged (comment-only cleanup around version declaration, compile helpers, wordlist/timer handling, and autoload path handling). 2026-02-25 01:58:19 -07:00
1bf0140652 Cleaned up redundant inline comments in the SCRAM implementation so the file is less noisy while preserving behavior exactly as-is (no logic changes). 2026-02-25 01:54:34 -07:00
bb72f8afab Removed redundant inline comments from the common header includes/platform guards in src/common/zoitechat.h (e.g., comments like “need time_t”, “for win32”, “for unix”), while preserving meaningful explanatory comments. 2026-02-25 01:50:00 -07:00
bb11c4676b Cleaned up src/fe-gtk/meson.build by removing an outdated commented-out WinRT build block in the Windows section, leaving only active build logic.
Removed an inline TODO comment from the gnome.compile_resources call to keep the Meson configuration concise and focused on current settings.
2026-02-25 01:47:32 -07:00
32fe3e54f1 Removed redundant section-divider comments in the Windows spellcheck provider to reduce clutter without changing behavior.
Removed non-essential inline comments that restated obvious return values and assignment intent (return -1/1/0, add_to_exclude alias), keeping logic identical.
2026-02-25 01:45:20 -07:00
9d2187ca4d Cleaned up unneeded inline comments in src/fe-text/fe-text.c where control-character switch cases were already self-explanatory, while keeping behavior unchanged.
Removed a redundant comment from the done global flag declaration for a cleaner declaration section.
2026-02-25 01:43:01 -07:00
0e94432c24 Removed four redundant comments in plugins/sysinfo/sysinfo.c while keeping behavior unchanged (the command parsing, channel checks, and menu add/remove calls are intact). 2026-02-25 01:40:34 -07:00
c4890d157a Cleaned up redundant inline comments in the exec plugin’s command execution path (pipe creation, buffer termination, per-line announce handling, sleep loop, and trailing newline output) without changing behavior. 2026-02-25 01:38:06 -07:00
ef2befa698 Cleaned up redundant comments in src/fe-gtk/fkeys.c by removing section-divider noise and a stale XXX line near key-action helpers, while keeping useful function-level documentation.
Removed repetitive inline comments from return 2; statements in tab-move/history key actions, since behavior is already clear from the surrounding code.
Removed an unnecessary separator comment before replace_handle() for a cleaner transition between functions.
2026-02-25 01:35:30 -07:00
5f9ce549f8 Removed redundant inline comments in the timer plugin that did not add useful context (plugin handle declaration and return value comment), keeping behavior unchanged.
Removed an obsolete visual alignment guide comment above the timer list header print call to clean up the function body.
2026-02-25 01:32:27 -07:00
cb435f0d15 Cleaned up unneeded comments in default config initialization by removing:
a stale commented-out assignment line,

    an outdated inline TODO/FIXME note on hex_irc_who_join,

    and an inline /*FIXME*/ marker on hex_flood_msg_time.
2026-02-25 01:29:05 -07:00
105e259f2c Removed redundant inline /* plugin handle */ comments from the ph declarations in three plugin source files, keeping behavior unchanged and making the declarations cleaner. 2026-02-25 01:06:13 -07:00
51bf0c3fe0 Removed redundant explanatory comments in chanopt_command so the control flow reads cleanly without inline narration, while keeping behavior unchanged.
Simplified the chanopt_in_memory struct and helper routines by removing comments that repeated obvious intent (allocation/default initialization/loading notes), with no logic changes.
2026-02-25 01:02:37 -07:00
e6311a5fe7 Removed two stale, commented-out lines in ignore_showlist() (an unused EMIT_SIGNAL call and its note), cleaning up unneeded comments without changing runtime behavior. 2026-02-25 00:59:53 -07:00
2c90c14d72 Removed an unneeded comment above the $(CONFIG_STAMP) target in Makefile, leaving behavior unchanged and just cleaning up the file. 2026-02-25 00:57:30 -07:00
6c9aeac36f Cleaned up unneeded inline comments in swtype by removing index/reserved annotations that didn’t add value, while keeping the data unchanged.
Removed a stale commented-out ST_HEADER line from tabs_settings so the settings table only contains active entries.
Removed a dead commented-out call from setup_apply_trans to reduce noise in the function body.
Removed redundant trailing declaration comments from proxy_user and proxy_pass since the types are already explicit.
2026-02-25 00:55:37 -07:00
48f7693eac Removed redundant comments in the notification plugin implementation to clean up the code without changing behavior (including comments around color stripping, alert gating logic, and special-event hook registration). 2026-02-25 00:53:10 -07:00
71d3ba576f Removed an outdated TODO comment in plugins/python/python.py above the module-level state variables, keeping behavior unchanged while reducing noise.
Removed two stale TODO comments in plugins/python/_zoitechat.py above command() and hook_command(), with no functional changes to those APIs.
2026-02-25 00:49:54 -07:00
067670bd01 Removed three redundant inline comments in the server helper code to clean up readability without changing any behavior:
Deleted comment above the serv->network check in server_get_network.
 Deleted comment above the server_session->channel check in server_get_network.
 Deleted comment above the name != serv->servername guard in server_set_name.
2026-02-25 00:46:18 -07:00
610d6fa1c0 Removed stale, commented-out SSL debug code in ssl_cb_info, leaving the function behavior unchanged while cleaning dead comments.
Removed an old commented-out rsa_tmp_bits certificate logging block in the SSL certificate info path.
Removed commented-out “Verify OK” signal lines in the SSL verification switch for cleaner control-flow comments.
2026-02-25 00:43:03 -07:00
5d6fa503c9 Cleaned up redundant CI workflow comments in AppImage workflow sections where the commands are already self-explanatory, including plugin listing and environment export blocks.
Replaced a long explanatory Solus packaging comment block with a concise single-line comment that preserves the key intent for --ignore-file-conflicts and toolchain installation.
Removed unneeded inline comments in the Windows build workflow around Python root resolution and junction creation while keeping behavior unchanged.
2026-02-25 00:40:36 -07:00
375e747014 Removed four redundant section-label comments from plugins/python/generate_plugin.py to clean up non-essential commentary while keeping behavior unchanged (# zoitechat-plugin.h, # This is very specific..., # python.py, # python.c). 2026-02-25 00:38:03 -07:00
5cab7be8a9 Removed redundant inline comments in notify network filtering and server-entry lookup paths to clean up noise without changing behavior.
Simplified notify list preparation in notify_save into a single reverse-copy expression and normalized GLib call spacing for consistency.
2026-02-25 00:34:59 -07:00
4808d83b26 Cleaned up unneeded inline comments in IRC inbound handling by removing redundant // comments around session selection and SCRAM auth status branches, with no logic changes. 2026-02-25 00:32:23 -07:00
c4951a06f3 Cleaned up unneeded commented-out debug lines in maingui.c (old printf/puts and an obsolete commented call), without changing behavior or logic flow.
Committed the cleanup on the current branch with commit message: Remove stale debug comments from maingui.
2026-02-25 00:29:52 -07:00
bd418160e1 Removed four redundant inline comments in print_sha256_result so the function is cleaner without changing behavior or control flow. 2026-02-25 00:26:56 -07:00
90a3d6d839 Removed redundant comments in url_save_node() and url_add() so the function bodies are cleaner without changing logic.
Removed an outdated performance note comment before the cached match state variables and a redundant comment in match_nick(); behavior remains unchanged.
2026-02-25 00:23:42 -07:00
deepend-tildeclub
e2511e8be1 Delete .github/workflows/debian-build.yml 2026-02-24 22:41:00 -07:00
deepend-tildeclub
33e1403b98 Delete debian directory 2026-02-24 22:40:49 -07:00
deepend-tildeclub
596a134ef3 Add Manjaro Package Build badge to README 2026-02-24 22:11:51 -07:00
85 changed files with 1966 additions and 1982 deletions

View File

@@ -1,48 +0,0 @@
name: Debian Build
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
debian_build:
runs-on: ubuntu-24.04
container:
image: debian:bookworm
steps:
- name: Install packaging tooling and build dependencies
run: |
set -eux
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y --no-install-recommends \
git ca-certificates \
build-essential dpkg-dev debhelper fakeroot \
pkg-config meson ninja-build \
gettext iso-codes \
libcanberra-dev libdbus-glib-1-dev libglib2.0-dev libgtk-3-dev libayatana-appindicator3-dev \
liblua5.3-dev libpci-dev libperl-dev libssl-dev \
python3-dev python3-cffi desktop-file-utils
- uses: actions/checkout@v4
with:
submodules: true
- name: Build Debian packages
run: |
set -eux
dpkg-buildpackage -us -uc -b
- name: Collect Debian artifacts
run: |
set -eux
mkdir -p artifacts
cp -v ../*.deb ../*.changes ../*.buildinfo artifacts/
- name: Upload Debian artifacts
uses: actions/upload-artifact@v4
with:
name: zoitechat-debian-packages
path: artifacts/*

View File

@@ -62,17 +62,8 @@ jobs:
sh -lc '
set -euo pipefail
eopkg update-repo -y
# Do not remove openssl-11 here: it can trigger a very large
# dependency cascade (including python3/eopkg itself), which
# breaks the build environment before package build starts.
# Some Solus base images still contain openssl-11 files that
# conflict with openssl 3.x when the package set is refreshed.
# Allowing file-conflict resolution keeps the CI image usable
# long enough to install ypkg and complete the package build.
# The base image does not guarantee Meson toolchain packages,
# while our package.yml setup phase calls meson directly.
# Install the essential build tools up front to avoid
# `/tmp/ypkg-setup*: meson: command not found` failures.
# Keep file-conflict handling on: some base images still carry
# openssl-11 leftovers, and Meson tooling is not always preinstalled.
eopkg install -y --ignore-file-conflicts \
ypkg git meson ninja pkgconf gcc gettext
ypkg build "$PACKAGE_YML"

View File

@@ -54,11 +54,9 @@ jobs:
Invoke-WebRequest 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.20\${{ matrix.platform }}
# Resolve python root from setup-python
$pyRoot = $env:pythonLocation
if (-not $pyRoot) { $pyRoot = & python -c "import sys; print(sys.prefix)" }
# Create BOTH paths because the .vcxproj hard-codes 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
$target = Join-Path $pyDir "${{ matrix.platform }}"

View File

@@ -14,7 +14,6 @@ CONFIG_STAMP := $(BUILD_DIR)/build.ninja
all: build
# Only run initial meson setup if we don't have a configured build dir yet.
$(CONFIG_STAMP):
@mkdir -p $(BUILD_DIR)
@env NINJA=$(NINJA) $(MESON) setup $(BUILD_DIR) --prefix=$(PREFIX) $(MESON_SETUP_ARGS)

View File

@@ -3,7 +3,11 @@
<id>net.zoite.Zoitechat</id>
<name>ZoiteChat</name>
<launchable type="desktop-id">net.zoite.Zoitechat.desktop</launchable>
<developer_name>ZoiteChat</developer_name>
<developer id="net.zoite">
<name translate="no">ZoiteChat</name>
</developer>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<translation type="gettext">zoitechat</translation>
@@ -12,7 +16,7 @@
<p>ZoiteChat is an easy to use yet extensible IRC Client based on Hexchat. It allows you to securely join multiple networks and talk to users privately or in channels using a customizable interface. You can even transfer files.</p>
<p>ZoiteChat supports features such as: DCC, SASL, proxies, spellcheck, alerts, logging, custom themes, and Python/Perl scripts.</p>
</description>
<url type="homepage">http://zoitechat.zoite.net</url>
<url type="homepage">https://zoitechat.zoite.net</url>
<url type="bugtracker">https://github.com/zoitechat/zoitechat</url>
<url type="help">https://docs.zoitechat.zoite.net/en/latest/</url>
<screenshots>
@@ -36,7 +40,7 @@
</ul>
</description>
</release>
<release date="2026-02-16" version="2.18.0-pre1">
<release date="2026-02-16" version="2.18.0~pre1">
<description>
<p>Packaging and GTK3 improvements:</p>
<ul>
@@ -234,5 +238,5 @@
<content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
</content_rating>
<update_contact>tingping_at_fedoraproject.org</update_contact>
<update_contact>deepend_at_zoite.net</update_contact>
</component>

521
debian/changelog vendored
View File

@@ -1,521 +0,0 @@
zoitechat (2.18.0~pre2-1) unstable; urgency=medium
* New upstream pre-release 2.18.0~pre2.
* Added HexChat plugin compatibility improvements.
* Fixed user info right-click menu refresh behavior.
* Added support for emoji characters in alert highlight matching.
* Removed remaining unused GTK2 code paths.
-- ZoiteChat Maintainers <zoitechat@users.noreply.github.com> Wed, 25 Feb 2026 02:16:43 +0000
zoitechat (2.18.0~pre1-1) unstable; urgency=medium
* New upstream pre-release 2.18.0~pre1.
* Debian packaging updates in this branch:
- switch package builds to GTK 3 and pass -Dgtk3=true to Meson.
- add/install split-package manifests for generated binary packages.
- include manpage and MIME package XML in package installs.
- adjust CI artifact staging/upload paths for actions/upload-artifact@v4.
-- ZoiteChat Maintainers <zoitechat@users.noreply.github.com> Sun, 16 Feb 2026 00:00:00 +0000
zoitechat (2.17.0-1) unstable; urgency=medium
* Switch Debian build to GTK 3 packaging:
- replace libgtk2.0-dev with libgtk-3-dev in Build-Depends.
- pass -Dgtk3=true to Meson during package builds.
- update package description to explicitly reference GTK 3.
-- ZoiteChat Maintainers <zoitechat@users.noreply.github.com> Sun, 16 Feb 2026 00:00:00 +0000
zoitechat (2.17.0-0) stable; urgency=medium
* Initial ZoiteChat packaging (forked from HexChat's Debian packaging).
* Rename packages/binaries to zoitechat.
* Move Python plugin package to Suggests (known to be unstable in Flatpak builds).
-- ZoiteChat Maintainers <zoitechat@users.noreply.github.com> Wed, 07 Jan 2026 00:00:00 +0000
hexchat (2.16.2-1) unstable; urgency=medium
* Update watch file for new github tarball location
* New upstream version 2.16.2
* Update copyright file
* Update copyright years also for Debian packaging
* Drop patch 0001-Be-even-more-picky-about-invalid-URLs.patch: upstream
* Add three patches from <pabs>:
- Add-channel-context-menu-item-to-close-the-channel,
- Automatically-reconnect-when-there-is-a-TLS-error,
- Do-not-insert-an-extra-space-on-all-lines-when-loading-scrollback-with-colours
-- Gianfranco Costamagna <locutusofborg@debian.org> Sat, 09 Mar 2024 11:51:16 +0100
hexchat (2.16.1-2) unstable; urgency=medium
[ Gianfranco Costamagna ]
* Team upload
[ Debian Janitor ]
* Drop versioned constraint on python3-dev.
[ Sudip Mukherjee ]
* Fix hexchat crash for specific links. (LP: #2029314)
+ This is an upstream cherry-pick
-- Gianfranco Costamagna <locutusofborg@debian.org> Wed, 06 Mar 2024 07:30:56 +0100
hexchat (2.16.1-1) unstable; urgency=medium
* New upstream version 2.16.1.
* Drop all patches, applied upstream.
-- Mattia Rizzolo <mattia@debian.org> Fri, 22 Apr 2022 21:52:27 +0200
hexchat (2.16.0-4) unstable; urgency=medium
* d/copyright: bump copyright year
* Add some patches from upstream, while waiting for the new release:
+ Fix build with OpenSSL 3.
+ Improve the fishlim tests.
+ Fix the URL opening to not double-encode already encoded URLs.
-- Mattia Rizzolo <mattia@debian.org> Mon, 17 Jan 2022 13:26:58 +0100
hexchat (2.16.0-3) unstable; urgency=medium
* Increase the tests timeout even more.
-- Mattia Rizzolo <mattia@debian.org> Sun, 31 Oct 2021 17:45:43 +0100
hexchat (2.16.0-2) unstable; urgency=medium
* Add patch to increase the tests timeout.
* Update our copy of the upstream changelog.
* Recommends:hexchat-lua from hexchat. Closes: #996172
Thanks to Jesse Rhodes <jesse@sney.ca> for the patch!
-- Mattia Rizzolo <mattia@debian.org> Fri, 15 Oct 2021 14:20:31 +0200
hexchat (2.16.0-1) unstable; urgency=medium
[ Mattia Rizzolo ]
* New upstream version 2.16.0.
+ Drop all patches applied upstream.
+ Refresh the patches tweaking the default channels/networks.
* Refresh the upstream signing key.
* Update copyright.
* Drop our patch renaming the Python plugin into Python3.
There doesn't seem to be any transition needed.
* d/control:
+ Drop Build-Depends on libnotify-dev and libproxy-dev,
not used anymore starting with v2.16.
+ Have hexchat-python3 Depend on python3-cffi-backend;
seems like I missed this dependency since v2.14.3-4.
+ Bump Standards-Version to 4.6.0, no changes needed.
[ Debian Janitor ]
* Remove constraints unnecessary since buster:
* Build-Depends: Drop versioned constraint on meson.
-- Mattia Rizzolo <mattia@debian.org> Mon, 04 Oct 2021 17:12:52 +0200
hexchat (2.14.3-6) unstable; urgency=medium
* Add Recommends:ca-certificates.
* Add patches from upstream to add Libera.Chat to the network list.
* Adapt default servers patches for the upstream changes.
* Ubuntu default server: LP: #1933681
+ Change from Freenode to Libera.Chat.
+ Pre-select the "join channel" button, like we do in Debian.
-- Mattia Rizzolo <mattia@debian.org> Wed, 26 May 2021 14:55:10 +0200
hexchat (2.14.3-5) unstable; urgency=medium
* Bump copyright for 2021.
* Apply patch from upstream to fix font height calculation with Pango>=1.44.
LP: #1920974
-- Mattia Rizzolo <mattia@debian.org> Sat, 02 Jan 2021 16:31:39 +0100
hexchat (2.14.3-4) unstable; urgency=medium
[ Debian Janitor ]
* Set upstream metadata fields: Bug-Submit.
[ Mattia Rizzolo ]
* Bump Standards-Version to 4.5.1, no changes needed.
* Bump debhelper compat version to 13.
+ Drop dh_missing override, now that --fail-missing is the default.
* Add a patch series from upstream to refactor the whole Python plugin,
using CFFI. This fixes support for Python 3.9. Closes: #975393
+ Replace my naive patch to fix the build with Python 3.8, using instead
the fix that comes from upstream.
+ Install the new files produced by cffi.
+ Add new Build-Depends python3-cffi.
-- Mattia Rizzolo <mattia@debian.org> Wed, 16 Dec 2020 22:03:57 +0100
hexchat (2.14.3-3) unstable; urgency=medium
* Add patch to use the new -embed variant of python3.pc.
Fix linking with Python 3.8. LP: #1866081
* Swap the Recommends:hwdata with Recommends:pci.ids. Closes: #953300
* Bump Standards-Version to 4.5.0, no changes needed.
-- Mattia Rizzolo <mattia@debian.org> Wed, 11 Mar 2020 17:08:25 +0100
hexchat (2.14.3-2) unstable; urgency=medium
[ Gianfranco Costamagna ]
* Refresh the Ubuntu servlist patch.
[ Mattia Rizzolo ]
* Import patch from upstream (from James Clarke) to properly prioritize
MODE commands, that were delaying PINGs in some cases.
[ Debian Janitor ]
* Set upstream metadata fields: Bug-Database, Repository,
Repository-Browse.
-- Mattia Rizzolo <mattia@debian.org> Thu, 02 Jan 2020 09:46:24 +0100
hexchat (2.14.3-1) unstable; urgency=medium
* New upstream version 2.14.3.
+ Drop patches applied upstream.
* d/control:
+ Bump build-dependency on meson to >= 0.40.
+ Bump Standards-Version to 4.4.1, no changes needed.
* Update the boundled upstream docs.
-- Mattia Rizzolo <mattia@debian.org> Tue, 31 Dec 2019 15:24:45 +0100
hexchat (2.14.2-5) unstable; urgency=medium
* Stop building the Python2 plugin. Closes: #936697
Simplify the patch used to build py2 and py3; we need to keep it because
we used to rename the 'python' plugin to 'python3'. We should check if
some kind of transition should be done to go back to the upstream
defaults.
* d/control:
+ Drop a bunch of old Breaks/Replaces that shouldn't be needed anymore.
+ Bump Standards-Version to 4.4.0, no changes needed.
+ Bump debhelper compat level to 12, no changes needed.
-- Mattia Rizzolo <mattia@debian.org> Sat, 31 Aug 2019 11:57:51 +0200
hexchat (2.14.2-4) unstable; urgency=medium
* Add a patch to fix a probable crash while unloading the Python plugin
when using Python 3.7. LP: #1830246; Closes: #921208
-- Mattia Rizzolo <mattia@debian.org> Sat, 25 May 2019 11:48:26 +0200
hexchat (2.14.2-3) unstable; urgency=medium
[ Ondřej Nový ]
* d/copyright: Change Format URL to correct one.
[ Mattia Rizzolo ]
* Move the patches tweaking the default servers out of d/patches, and inject
them through d/rules. The ctte decided that vendored series files are not
allowed in the Debian archive, see #904302. Closes: #915350
-- Mattia Rizzolo <mattia@debian.org> Mon, 03 Dec 2018 14:17:35 +0100
hexchat (2.14.2-2) unstable; urgency=medium
* Add patch to fix FTBFS on !linux.
* d/control: Use the new debhelper-compat(=11) build-dep and drop d/compat.
-- Mattia Rizzolo <mattia@debian.org> Sun, 23 Sep 2018 20:38:39 +0200
hexchat (2.14.2-1) unstable; urgency=medium
* New upstream version 2.14.2.
* d/patches:
+ Drop patches applied upstream.
+ Refresh remaining patches.
* d/control: Bump Standards-Version to 4.2.1, no changes needed.
-- Mattia Rizzolo <mattia@debian.org> Sat, 01 Sep 2018 22:28:20 +0200
hexchat (2.14.1-2) unstable; urgency=medium
* Add some patches from upstream:
+ upstream/0003-Remove-shift-click-to-close-tab-binding.patch
- LP: #1756402
+ upstream/0004-build-Add-metainfo-files-for-addons.patch
+ upstream/0005-build-Fix-id-in-plugin-metainfo-files.patch
+ upstream/0006-build-Correctly-set-plugin-licenses.patch
+ upstream/0007-build-Re-add-support-for-the-legacy-perl-api.patch
+ upstream/0008-Deiconify-window-on-tray-click.-Closes-2136.patch
* Fixup our py2+py3 patch after the above patches have been applied.
* Install the new metainfo files representing the various plugins.
-- Mattia Rizzolo <mattia@debian.org> Tue, 20 Mar 2018 16:10:27 +0100
hexchat (2.14.1-1) unstable; urgency=medium
* New upstream version 2.14.1.
* Drop all patches applied upstream.
-- Mattia Rizzolo <mattia@debian.org> Wed, 14 Mar 2018 03:35:41 +0100
hexchat (2.14.0-1) unstable; urgency=medium
* New upstream version 2.14.0. Closes: #892085
* Refresh patches:
+ drop 4c178782a779f013fafab476506f7d4dae372b8a.patch, applied upstream.
+ Rewrite the local patch used to build for both python2 and python3 after
the change of build system upstream.
+ Add all the commits from upstream after the release:
- 0003-build-Remove-pie-from-global-ldflags.patch
- 0004-Fix-fscanf-usage-without-size-limit.patch
- 0005-fix-typo-in-comment.patch
- 0006-Revert-xtext-Always-use-Pango-to-get-correct-glyph-w.patch
* d/control:
+ Update build dependencies for the new upstream:
- New build-deps: gettext, iso-codes, liblua5.3-dev, meson (>= 0.38).
- Drop build-deps: dh-lua, intltool, libtool.
- Drop version restriction from libgtk2.0-dev (>= 2.10.0).
+ Set Rules-Requires-Root:no.
* d/changelog.txt: Update from upstream.
* d/hexchat.install: Slightly update the paths.
* d/rules:
+ Drop override_dh_install not needed anymore with meson.
+ Explicitly build with lua 5.3. The new build system defaults on luajit
only now.
* d/copyright: Update.
-- Mattia Rizzolo <mattia@debian.org> Wed, 14 Mar 2018 02:36:37 +0100
hexchat (2.12.4-6) unstable; urgency=medium
* d/control:
+ Move packaging to salsa.debian.org.
+ Replace recomendency on gvfs-bin to libglib2.0-bin. Closes: #877746
+ Bump Standards-Version to 4.1.3, no changes needed.
* d/copyright: Bump copyright years for debian/*.
* d/rules: Replace dh_install --fail-missing by dh_missing.
* d/watch: Use HTTPS.
* Bump debhelper compat level to 11.
-- Mattia Rizzolo <mattia@debian.org> Sat, 24 Feb 2018 18:26:41 +0100
hexchat (2.12.4-5) unstable; urgency=medium
* Add a short description to the previous changelog entry on how to manually
preserve the scrollback that would otherwise get lost.
* Remove the patch also for Ubuntu (fixing FTBFS there).
* d/control:
+ Add a bunch of Multi-Arch:same notation, suggested by the M-A hinter.
+ Remove the transitional package hexchat-python.
-- Mattia Rizzolo <mattia@debian.org> Sat, 15 Jul 2017 18:34:27 +0200
hexchat (2.12.4-4) unstable; urgency=medium
* Stop reverting upstream commit 15600f405f2d5bda6ccf0dd73957395716e0d4d3.
This means users will lose their scrollback right after updating, but
that's what upstream did and we have no real reasons to undefinitely
diverge from them just to wait for a nicer fix.
Closes: #852275; CVE-2016-2087
For users who care about their scrollback, it's enough to manually rename
the directories in ~/.config/hexchat/scrollback to all-lowercase characters
before restarting hexchat after the update.
* d/control: Bump Standards-Version to 4.0.0, no changes needed
* d/copyright: bump my copyright year for debian/ to cover 2017
-- Mattia Rizzolo <mattia@debian.org> Fri, 14 Jul 2017 16:12:32 +0200
hexchat (2.12.4-3) unstable; urgency=medium
* Demote hexchat-otr from Recommends to Suggests.
It reportely causes noise and problems for unexperienced users, and it's
a mostly unmaintained plugin, so don't install it by default.
-- Mattia Rizzolo <mattia@debian.org> Tue, 30 May 2017 21:50:09 +0200
hexchat (2.12.4-2) unstable; urgency=medium
* Also apply patch 4c178782a779f013fafab476506f7d4dae372b8a.patch on ubuntu.
* d/p/0001-Debian-server-defaults.patch: Add missing braces around the `if`.
Thanks to Lauri Alanko <la@iki.fi> for the patch. Closes: #779892
-- Mattia Rizzolo <mattia@debian.org> Thu, 26 Jan 2017 09:54:41 +0100
hexchat (2.12.4-1) unstable; urgency=medium
* New upstream version 2.12.4.
* d/copyright: update (removal of the doat plugin).
* d/watch: improve:
+ Bump version to 4.
+ Use substitution strings @ANY_VERSION@ and @ARCHIVE_EXT@.
+ Ignore version 2.12.4-repack by mangling it into 2.12.4.
* d/control: mark hexchat-dev and hexchat-lua as Multi-Arch:same.
* d/patches/:
+ openssl/*: drop, applied upstream.
+ clean.patch: drop, applied upstream.
+ 4c178782a779f013fafab476506f7d4dae372b8a.patch: include from upstream to
work around a gdk-pixbuf bug which would prevent the hexchat icon from
being displayed in panels/systrays. Closes: #848615
* d/rules: add a 'udoc' target to update the bundled copy of upstream doc.
* Update upstream documentation.
* d/hexchat-plugins.install: upstream converted the 'doat' plugin into an
internal command, so stop trying to install the plugin.
-- Mattia Rizzolo <mattia@debian.org> Mon, 26 Dec 2016 01:16:19 +0100
hexchat (2.12.3-4) unstable; urgency=medium
* Re-enable Lua support everywhere now that #845929 is fixed.
-- Mattia Rizzolo <mattia@debian.org> Mon, 19 Dec 2016 12:47:31 +0100
hexchat (2.12.3-3) unstable; urgency=medium
* Actually disable Lua support when building.
-- Mattia Rizzolo <mattia@debian.org> Mon, 05 Dec 2016 16:03:26 +0100
hexchat (2.12.3-2) unstable; urgency=medium
* Temporary restrict the build of hexchat-lua to the architectures where lua
is usable right now (see #845929).
-- Mattia Rizzolo <mattia@debian.org> Mon, 05 Dec 2016 14:02:40 +0100
hexchat (2.12.3-1) unstable; urgency=medium
[ Jesse Rhodes ]
* Add hexchat-dev package for .pc and .h files.
* Include dbus service file in hexchat-common.
[ Mattia Rizzolo ]
* Take over maintenance from Jasse Rhodes.
Thank you for all your work these years! Closes: #844574
* debian/control:
+ wrap-and-sort -ast.
+ Bump Standards-Version to 3.9.8, no changes needed.
+ Add proper Breaks/Replaces for the hexchat-dev addition-
+ Have hexchat-plugins recommend hwdata for the sysinfo plugin.
Closes: #845940
+ Have hexchat recommend the hexchat-otr plugin.
Thanks to Petter Reinholdtsen <pere@hungry.com> for the suggestion
+ Bump the Breaks/Replaces of hexchat-plugins against hexchat;
hexchat-plugin.pc has been moved from hexchat to hexchat-plugins
in 2.12.0-1. LP: #1586239
+ Set appropriate Breaks/Replaces to cope with the Ubuntu delta and
make the package syncable.
+ Mark hexchat-common as Multi-Arch:foreign (from the m-a hinter).
* debian/rules:
+ Remove huge override_dh_auto_clean: if anything of that is needed,
it should be done on the upstream side.
+ Remove *.la files before running dh_install.
+ Use dh_install --fail-missing.
* Package the Lua plugin. Closes: #834491
* Update upstream changelog for 2.13.2.
* Use dh_installchangelogs to install the upstream changelog, instead of
manually compressing in rules and the install with d/*.docs.
* Let the upstream build system put the manpage in place, instead of copying
it of our own.
* Add patch to properly clean the upstream sources and make possible to build
the package twice in a row.
* Bump debhelper compat level to 10.
+ --with autoreconf is now default.
* debian/copyright:
+ Make it DEP-5 compliant.
+ Update.
* Drop nearly all lintian overrides; they are either fixed or unused.
-- Mattia Rizzolo <mattia@debian.org> Thu, 01 Dec 2016 18:30:03 +0100
hexchat (2.12.3-0.1) unstable; urgency=medium
* Non-maintainer upload, with maintainer ACK.
[ Jesse Rhodes ]
* Fixed vcs-git url.
[ Mattia Rizzolo ]
* Imported Upstream version 2.12.3. Closes: #836809
* Refresh patches
* d/rules: disable LUA bindings, as they would require a new binary package.
* Add several patches from upstream to add support to OpenSSL 1.1.0.
Closes: #828339
* Revert upstream commit 15600f405f2d5bda6ccf0dd73957395716e0d4d3, which
would cause users to lose their scrollback.
-- Mattia Rizzolo <mattia@debian.org> Sun, 27 Nov 2016 13:41:25 +0100
hexchat (2.12.0-2) unstable; urgency=medium
* Removed patch correcting for missing translations,
as translations are no longer missing
* Removed patch correcting spelling error that would break
some scripts and themes
* Updated ubuntu server/channel defaults
-- Jesse Rhodes <drubo@drubo.net> Wed, 30 Mar 2016 11:44:04 -0600
hexchat (2.12.0-1) unstable; urgency=medium
* New upstream release
* Iceweasel no longer called Firefox in url dialog
* Building both python2 and python3 plugins
* Including hexchat-plugin.pc (Closes: 801767)
-- Jesse Rhodes <drubo@drubo.net> Fri, 25 Mar 2016 10:54:57 -0600
hexchat (2.10.2-1) unstable; urgency=medium
* New upstream release
* Includes upstream fixes for POODLE vulnerability
(CVE-2014-3566)
* Split plugins into modular packages rather than having all
binaries in the main hexchat package
-- Jesse Rhodes <drubo@drubo.net> Fri, 28 Nov 2014 18:35:39 -0700
hexchat (2.10.1-2) unstable; urgency=medium
* Fix ubuntu_defaults.patch (LP: #1390851)
* Disable SSLv3
-- Jesse Rhodes <drubo@drubo.net> Sun, 16 Nov 2014 11:47:12 -0700
hexchat (2.10.1-1) unstable; urgency=medium
* New upstream release
* No longer build-depend on libsexy-dev
* URL handler dialog now labeled Iceweasel rather than Firefox
-- Jesse Rhodes <drubo@drubo.net> Mon, 18 Aug 2014 21:18:55 -0600
hexchat (2.10.0-1) unstable; urgency=medium
* New upstream release
* Removed patches for issues fixed by upstream
* Added default servers and recommended channels for debian
and ubuntu (LP: #1294415)
* Upstream commit fa955a0f fixes xdcc segfault (Closes: #745764)
-- Jesse Rhodes <drubo@drubo.net> Sun, 01 Jun 2014 16:45:22 -0600
hexchat (2.9.6.1-2) unstable; urgency=low
* Now using dh-autoreconf instead of autotools-dev (Closes: #739630)
* Added gvfs-bin as Recommends so default url handlers work
(Closes: #740006)
* Added unifont as Suggests for unicode symbol support
* Included png,svg icons in package
-- Jesse Rhodes <drubo@drubo.net> Tue, 25 Feb 2014 16:45:42 -0700
hexchat (2.9.6.1-1) unstable; urgency=low
* Initial release (Closes: #702075)
-- Jesse Rhodes <drubo@drubo.net> Mon, 03 Feb 2014 19:09:17 -0700

126
debian/control vendored
View File

@@ -1,126 +0,0 @@
Source: zoitechat
Section: net
Priority: optional
Maintainer: ZoiteChat Maintainers <zoitechat@users.noreply.github.com>
Build-Depends:
debhelper-compat (= 13),
gettext,
iso-codes,
libcanberra-dev,
libdbus-glib-1-dev,
libglib2.0-dev,
libgtk-3-dev,
liblua5.3-dev,
libpci-dev,
libperl-dev,
libssl-dev,
meson,
python3-cffi,
python3-dev
Standards-Version: 4.6.0
Rules-Requires-Root: no
Vcs-Git: https://github.com/zoitechat/zoitechat.git
Vcs-Browser: https://github.com/zoitechat/zoitechat
Homepage: https://zoitechat.zoite.net
Package: zoitechat
Architecture: any
Depends:
zoitechat-common (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Recommends:
ca-certificates,
zoitechat-lua,
zoitechat-perl,
zoitechat-plugins,
libglib2.0-bin
Suggests:
zoitechat-python3,
zoitechat-otr,
unifont
Description: IRC client for GNOME (fork of HexChat 2.18.0~pre2 base)
ZoiteChat is a graphical IRC client with a GTK 3 GUI. Features include Python,
Perl and Lua scripting support, a plugin API, multiple server/channel
windows, spell checking, multiple authentication methods including SASL, and
customizable notifications. For more information on IRC, see
http://irchelp.org/.
Package: zoitechat-common
Architecture: all
Multi-Arch: foreign
Provides: irc-client
Depends: ${misc:Depends}
Recommends:
ca-certificates,
zoitechat-lua,
zoitechat-perl,
zoitechat-plugins,
libglib2.0-bin
Suggests:
zoitechat,
zoitechat-python3,
zoitechat-otr,
unifont
Description: Common data files for ZoiteChat
This package includes architecture-independent files for ZoiteChat, such as
translations, desktop integration, and shared data.
Package: zoitechat-perl
Architecture: any
Multi-Arch: same
Depends:
zoitechat (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Description: Perl plugin for ZoiteChat
This package contains the Perl plugin for ZoiteChat. It is split out from the
main package because it is optional.
Package: zoitechat-python3
Architecture: any
Multi-Arch: same
Depends:
zoitechat (= ${binary:Version}),
python3-cffi-backend,
${misc:Depends},
${shlibs:Depends}
Description: Python 3 plugin for ZoiteChat
This package contains the Python 3 plugin for ZoiteChat. It is split out from
the main package because it is optional.
.
Known issue: the Python plugin may freeze the client in some builds.
Package: zoitechat-lua
Architecture: any
Multi-Arch: same
Depends:
zoitechat (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Description: Lua plugin for ZoiteChat
This package contains the Lua plugin for ZoiteChat. It is split out from the
main package because it is optional.
Package: zoitechat-plugins
Architecture: any
Multi-Arch: same
Depends:
zoitechat (= ${binary:Version}),
${misc:Depends},
${shlibs:Depends}
Suggests: pciutils
Description: Extra plugins for ZoiteChat
This package contains optional plugins (e.g. FiSHLiM, Sysinfo, Do At and
Checksum). These are split out from the main package because they are not
required for core functionality.
Package: zoitechat-dev
Architecture: any
Multi-Arch: same
Depends:
zoitechat-common (= ${binary:Version}),
${misc:Depends}
Description: Development files for ZoiteChat plugins
This package contains zoitechat-plugin.h and zoitechat-plugin.pc, which
facilitate building binary plugins for ZoiteChat.

188
debian/copyright vendored
View File

@@ -1,188 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: zoitechat
Source: https://zoitechat.zoite.net
Files: *
Copyright: 1998-2010 Peter Zelezny
2009-2013 Berke Viktor
2015-2021 Patrick Griffis
License: GPL-2+ with OpenSSL exception
Files: debian/*
Copyright: 2014 Jesse Rhodes <drubo@drubo.net>
2016-2022 Mattia Rizzolo <mattia@debian.org>
2020-2024 Gianfranco Costamagna <locutusofborg@debian.org>
License: GPL-2+
Files: data/man/zoitechat.1.in
Copyright: Davide Puricelli <evo@debian.org>
License: GPL-2+
Files: osx/gtkrc
Copyright: 2012 Xamarin Inc.
License: GPL-2+
Files: plugins/checksum/* plugins/exec/*
Copyright: 2010-2012 Berke Viktor
License: Expat
Files: plugins/fishlim/*
Copyright: 2010 Samuel Lidén Borell <samuel@kodafritt.se>
2015 <the.cypher@gmail.com>
2019-2020 <bakasura@protonmail.ch>
License: Expat
Files: plugins/lua/*
Copyright: 2015-2016 mniip
License: Expat
Files: plugins/perl/*
Copyright: 1998-2002 Peter Zelezny
License: GPL-2+
Files: plugins/python/*
Copyright: 2002-2003 Gustavo Niemeyer <niemeyer@conectiva.com>
License: GPL-2+
Files: plugins/sysinfo/*
Copyright: 2003-2005 Michael Shoup
2005-2007 Tony Vroon
2012 Berke Viktor
2015 Patrick Griffis
License: GPL-2+
Files: plugins/winamp/*
Copyright: Leo <leo.nard@free.fr>
Silverex <SilvereX@karklas.mif.vu.lt>
Derek Buitenhuis <daemon404@gmail.com>
Berke Viktor <berkeviktor@aol.com>
License: GPL-1.0
Files: src/common/dbus/*
Copyright: 2006 Claessens Xavier
License: GPL-2+
Files: src/common/dbus/example.py
Copyright: 1998-2010 Peter Zelezny
2009-2013 Berke Viktor
License: GPL-2+
Files: src/common/scram.*
Copyright: 2023 Patrick Okraku
License: GPL-2+
Files: src/common/ssl.c
Copyright: 2000 DaP <profeta@freemail.c3.hu>
License: GPL-2+ with OpenSSL exception
Files: src/dirent/dirent-win32.h
Copyright: 2006-2012 Toni Ronkko
License: Expat
Files: src/fe-gtk/sexy-iso-codes.c src/fe-gtk/sexy-iso-codes.h
Copyright: 2008 Novell, Inc.
2013 Sandro Mani
License: GPL-2+
Files: src/fe-gtk/sexy-spell-entry.c src/fe-gtk/sexy-spell-entry.h
Copyright: 2002 Evan Martin
2004-2006 Christian Hammond
License: LGPL-2.1+
License: GPL-2+ with OpenSSL exception
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-2'.
.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
You must obey the GNU General Public License in all respects for all of
the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete
this exception statement from your version. If you delete this exception
statement from all source files in the program, then also delete it here.
License: Expat
.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-2'.
License: GPL-1.0
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301, USA.
License: LGPL-2.1+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA

View File

@@ -1,40 +0,0 @@
Description: Changed default network to OFTC,
suggests to join #debian on OFTC and Freenode
diff --git a/src/common/servlist.c b/src/common/servlist.c
index a203e702..22fcd92b 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -902,7 +902,7 @@ servlist_load_defaults (void)
{
int i = 0, j = 0;
ircnet *net = NULL;
- guint def_hash = g_str_hash ("Libera.Chat");
+ guint def_hash = g_str_hash ("OFTC");
while (1)
{
diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index ce3cbcae..7f6b1116 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -247,10 +247,18 @@ joind_show_dialog (server *serv)
G_CALLBACK (joind_ok_cb), serv);
if (serv->network)
+ {
+ if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "OFTC") == 0)
+ {
+ gtk_entry_set_text (GTK_ENTRY (entry1), "#debian");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(radiobutton2), TRUE);
+ }
if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Libera.Chat") == 0)
{
- gtk_entry_set_text (GTK_ENTRY (entry1), "#hexchat");
+ gtk_entry_set_text (GTK_ENTRY (entry1), "#debian");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(radiobutton2), TRUE);
}
+ }
gtk_widget_grab_focus (okbutton1);
gtk_widget_show_all (dialog1);

View File

@@ -1,43 +0,0 @@
Description: Changed default channel to join from #hexchat to #ubuntu
Also adds a "Ubuntu servers" entry, same as connecting to libera.chat.
diff --git a/src/common/servlist.c b/src/common/servlist.c
index a203e702..18a6c4b3 100644
--- a/src/common/servlist.c
+++ b/src/common/servlist.c
@@ -206,6 +206,9 @@ static const struct defaultserver def[] =
{"Libera.Chat", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "irc.libera.chat"},
+ {"Ubuntu Servers (Libera.Chat)", 0, 0, 0, LOGIN_SASL, 0, TRUE},
+ {0, "irc.libera.chat"},
+
#ifdef USE_OPENSSL
{"LibertaCasa", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "irc.liberta.casa"},
@@ -902,7 +905,7 @@ servlist_load_defaults (void)
{
int i = 0, j = 0;
ircnet *net = NULL;
- guint def_hash = g_str_hash ("Libera.Chat");
+ guint def_hash = g_str_hash ("Ubuntu Servers (Libera.Chat)");
while (1)
{
diff --git a/src/fe-gtk/joind.c b/src/fe-gtk/joind.c
index ce3cbcae..e94e562a 100644
--- a/src/fe-gtk/joind.c
+++ b/src/fe-gtk/joind.c
@@ -247,9 +247,10 @@ joind_show_dialog (server *serv)
G_CALLBACK (joind_ok_cb), serv);
if (serv->network)
- if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Libera.Chat") == 0)
+ if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Ubuntu Servers (Libera.Chat)") == 0)
{
- gtk_entry_set_text (GTK_ENTRY (entry1), "#hexchat");
+ gtk_entry_set_text (GTK_ENTRY (entry1), "#ubuntu");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(radiobutton2), TRUE);
}
gtk_widget_grab_focus (okbutton1);

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>net.zoite.Zoitechat</id>
<name>ZoiteChat</name>
<summary>IRC client for GNOME</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0-or-later</project_license>
<description>
<p>ZoiteChat is a graphical IRC client based on HexChat.</p>
<p>Current Flatpak builds have a known issue where the Python plugin can freeze the client.</p>
</description>
<launchable type="desktop-id">net.zoite.Zoitechat.desktop</launchable>
<provides>
<binary>zoitechat</binary>
</provides>
<url type="homepage">https://zoitechat.zoite.net/</url>
</component>

View File

@@ -1 +0,0 @@
readmechanges.patch

22
debian/rules vendored
View File

@@ -1,22 +0,0 @@
#!/usr/bin/make -f
export DH_VERBOSE=1
%:
dh $@ --buildsystem=meson
override_dh_auto_configure:
dh_auto_configure -- \
-Dinstall-plugin-metainfo=false \
-Dwith-lua=lua53
override_dh_installchangelogs:
install -m0755 -d \
debian/zoitechat/usr/share/doc/zoitechat \
debian/zoitechat-common/usr/share/doc/zoitechat-common \
debian/zoitechat-perl/usr/share/doc/zoitechat-perl \
debian/zoitechat-python3/usr/share/doc/zoitechat-python3 \
debian/zoitechat-lua/usr/share/doc/zoitechat-lua \
debian/zoitechat-plugins/usr/share/doc/zoitechat-plugins \
debian/zoitechat-dev/usr/share/doc/zoitechat-dev
dh_installchangelogs changelog.rst

View File

@@ -1 +0,0 @@
3.0 (quilt)

View File

@@ -1,2 +0,0 @@
# the upstream maintainer says that he doesn't have time to go fish out his GPG key for now
orig-tarball-missing-upstream-signature

View File

@@ -1,4 +0,0 @@
Bug-Database: https://github.com/zoitechat/zoitechat/issues
Bug-Submit: https://github.com/zoitechat/zoitechat/issues/new
Repository: https://github.com/zoitechat/zoitechat.git
Repository-Browse: https://github.com/zoitechat/zoitechat

View File

@@ -1,72 +0,0 @@
pub rsa4096 2014-02-13 [SC] [expires: 2024-02-08]
108BF2212A051F4A72B18448B3C7CE210DE76DFC
uid [ unknown] Patrick Griffis <tingping@tingping.se>
uid [ unknown] TingPing <tingping@fedoraproject.org>
sub rsa4096 2014-02-13 [E] [expires: 2024-02-08]
C6CAF2A624B9C2ECBF83ACBF488A9319DABACE61
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFL9JHIBEADDKL+vc3MHctXCWxG0IcuLPm4i+WO9jH6MdF8p2bokaL5lilcJ
o2i0RHImP83FpqCDj/hE7AeB3Ix3Oq3tIe6lpCz468OVbLivErX/yL8rYUhC+yba
zlSJcBipTIezD3pZI/vpFyCIC8mSEI4PJGiLotioNJWQBStQuuPqMKo4cd6cRWx6
WovQMKa85rQPvv+wYCseBqU6xBx1xSgpkjDJnAH7We5G6T8TYVM2gqXtii/JYyUC
8E7Z2BBdSGkq1Dma1W6paOw7VOtLu6YbAH9v/VUVx0UdzwiyXHQ8qLKbxeXkex9d
zoe+oy8wt3bvVHirxU42IlJJVLY4NcUYhr/xOq/YqT+3sWAqgdVM/WnzY3bPiMnQ
XqQ3UZ0LKXXsF2+9u2qM6FTiAHIMLtH95IlOQo1qXmDl1HRJTNq3B41UduLDRUhP
uGBaXbOtb6ql4nV3/BTxcHumisMh5ALhqXHRNOdn+mEjvT2HT6pp07ZfVhFwM4U0
K78f52S+NppiS0cWtn9ibq+UmqZyvw9HMOHYt51lSUOueg/sOvsxrG1gjvcUMlJw
nCgS3b+QUmZYo+pl/l13fiWPQpteVGZqKPMBBaQ4MCrwHgvikN8uppKDw8fFGs44
LgbCsDoQA8wKxNzMEMTvuhFFgCiOxMCzR0XKxlcKr8CiHZjYwovJLFfLvwARAQAB
tCVUaW5nUGluZyA8dGluZ3BpbmdAZmVkb3JhcHJvamVjdC5vcmc+iQJVBBMBAgA/
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBBCL8iEqBR9KcrGESLPHziEN
5238BQJcXuBtBQkSx717AAoJELPHziEN5238pfAP/331a2PASeS1toBRNbMVyXcB
8zEb5Q4MFiTmgy7aOOo2MDzV4VBiYEUa93pmWrozWudqZl1u+Cm7XC0Kxv7b6HRC
/2UBDKY0FUk7xALFQN+XycNDweflT9SlJ+4IcgfHX3/FcF0Obl0fnNfr8DXXqdsj
hxWqlXRkyvRC8VuJJkkufi4CxUBQPSSG+dGgskACP6e210rogPq7LyUIMKkKqKSV
69RUHDJZOsObNA6q1gTNcb8G/lIGaqbVTJ/d+6X/iDkgMrxRi++OyAUa7aXMHGBn
5PnFjqPKBP7qrEEl1nA0LcXhr1hCEVVXGosuqR1WjbbyOTOq50oGvk8zbTy/1mOc
UwkJYbaMv20wAYXx9QSbYoTDMx+DXrB3NCtBHeM7o9igoom8n9khoVmC1SPMOsQM
1xLAk22RuyeDw3C3K3xoar4tcrwXKRmTyUxDBvkR7gtySiAKWFZOEPbeeRzprpG+
Fg48Zh7buqh3Rdk5rmXOeATbyRq9+D0p6WhtO6UdEbi9yNCGo/eTTs2a9CcxfW6E
7gGrX/wP6eKrP7KiT5NqcM01R961IxRpNLM0Uy15Jf5paP9VoJBtR0hO+94Vc9ZJ
jS9yv5iJ62FIqSkqXZ7v+59XFZjm84pI7ywHuzjv9poBi3W19jM1eyYeryLj8362
w2z5UgLfllZv1o2NTLx6tCZQYXRyaWNrIEdyaWZmaXMgPHRpbmdwaW5nQHRpbmdw
aW5nLnNlPokCVAQTAQgAPgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBBCL
8iEqBR9KcrGESLPHziEN5238BQJcXuBtBQkSx717AAoJELPHziEN5238J9cP/3SX
UCZBFKf79LUfKVOxZYgAMKzL2CQdglNKrtE0aqMJwga6AUrSLEBWUqKHOFrcWYDi
qKldpWGWv52lSlZL4YCIcgymOyYMbjQXkHUUaAH4tCzjT0yhFKKAAokJKBSinaO4
cA6i3p3XdyUWbvjqnc8/2Mn31cyxiqj58EN5r7naS/5DaD+0q2dxhLW5/A+IKukk
l12NhMpDbTkQ18brttBMCW5h5LPR7HDN5hVPCztj4BN5JqPeMyspemvGMT6G12vA
5N+S83rAushIyu8Y88iKhPsNLbLgi3PCOZJDKeNlqdPoXJX7mau41U08/8NiORUP
R4Dj9942c6rdHHXDyZ3puvsVK0YjwcmG5uSdG2tpyhNOBiyNQXgpPVHU5YKTob75
vGs4uuxKYxNns/UULiC4fp/gGOIRh9f0veJG2DbMnEHXhnpQzIbsYSo1yeJ+8vFM
FhbkHlylrkTUtOzQwFqybhgYGbfDvT4weMvCc9jEQXfIfI39/Tjx/JD0VVKu577X
oZhtsb4rX2qEmiEnMrWAMM97LGyCNEi6DJipHse4Z5cc54/VswGF8Ze4VYF5hF8o
DaIQfGXmuceMS3l4FXK0x6CYKpr7e0pY3zrsGIJ8Zwd11T9ubilAvK68Ix7j1puJ
x8/ZD9NYP/NUNpriRVyFNiPlfKRqauDBnSKjiTiguQINBFL9JHIBEACx1FJWBK1R
ORu+rHa52Uc0+Jkcr791A10Itwyv6fsA0RT6moob6s8Rvet8NQH6SZVRqiGy3d8g
lxnedT32ZxHWRoLC8Pc6PnQhVXB3RSZoE9VVm9z+7nHOGXXCj0a0OsgyGSHLerE9
7MvlMlkf2EsOTj6irZZDvJH4Eblbk1WzC4K5EC5r7FL/4sdHLbDWEUR3wemC7s0n
9IusHwNBiTSSxpag/dq9+6eVyoA3opsqSU3wlSqfm3U/0G3MG4JkwDmS3nK4hmmq
nCakdXZaqKZDGZjfaztTuO5RP73KfNHSNfsreOXY3ldX7Jy1qdHp/hBp6CFXhHul
d4ZyWL+O6uMRcNQdfd/b8VBDe3z2LYw3AHnhjAnmwJqjfnhH3r7ibM2+HAtrj8J5
Qwe/28QJOR3UfT1+tYW8I0bpnBesfzgm9Vp2t3IzkaGdXQOsB9KdcKRV4viiq4VP
S1HdtvpLAxxrNxFguIlYAkLMJwwuaaK8X+K/kgAm3q5+txsxR/jDmDaFqqj0YnfT
7s+czbSkkvXDG68sTVr1c2u71i8Q0XXSSrL30/j/+//CN9mP6oI6dYRDK5wCFaYw
cQe5Td/biJDWXsXolOC0CHny1TTfNvaK+b0Yksas7aLypHOc5xfVJI1eovwkBpXA
QQDFJoWlZudXXUvjPFsEyt9jd2LUl5fZcQARAQABiQI8BBgBAgAmAhsMFiEEEIvy
ISoFH0pysYRIs8fOIQ3nbfwFAlxe4JAFCRLHvZ4ACgkQs8fOIQ3nbfwvsQ//QE7v
neqZdFBq9PxIgu6S95PTchBI3BsCH6M3uv/hIpLgZwGzymHjCQlwYzjPYRAycphk
VjsWP5T6hFPDfFhtAkdPuDd6LW+asUky1B8t802jGrVSmEA81s9jkjKBpdNR5JJr
a8fAhUvZz9HW2SUwJyvVaO+q4GZep7VrNMKoCvC0K123V442wOYOLC3cldRgVRKY
tXs4KHEjYaR0+zvX2zJvn/CIHWaxw2/qgArXIbTqwiqOWeXAkQWwcArZzkughGIb
iv1DgkttTBLOZbiEUerwoMlGERlSTurhahoNInXD8vPPOrYMl7RSV8XUmgTKCJeN
Xv/Jdg7ejfmPH9zABh8kh+eiL/yINwh2mmRK2aM+u8wghU7i0g72GSKBNgPHzw7X
FDIN4diVX8MB93yeMOMzXGuyHzy3mQhj5LcqMKtTSOeqREAUTHoC0KvQ8kTeZ4N3
czHndwBNEVxluR4ljQeqMdJHWoy6GxFGdrcAHqLZZyxbBQq2cYMwAdbscnQqIhhC
luJgu4vA+7b8RQIZ725Ij+05J5vpHbPtEGACD09YChQL0OtLIZfS8RKP1lKLrmXC
cnJzweMcISPi5PxPXlqXNFzwspK2PLHpmwZ1zSoARXB3BzzCYTE4Mw8UxsCqpbDG
cBfbvGaxikGVOqMEoNo/umEhsyleb0gqXIoZJrc=
=kssP
-----END PGP PUBLIC KEY BLOCK-----

5
debian/watch vendored
View File

@@ -1,5 +0,0 @@
version=4
opts="searchmode=plain,\
filenamemangle=s%.*/v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%" \
https://api.github.com/repos/zoitechat/zoitechat/releases?per_page=50 \
https://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@

View File

@@ -1,7 +0,0 @@
usr/share/applications/net.zoite.Zoitechat.desktop
usr/share/dbus-1/services/org.zoitechat.service.service
usr/share/icons/hicolor/48x48/apps/net.zoite.Zoitechat.png
usr/share/icons/hicolor/scalable/apps/net.zoite.Zoitechat.svg
usr/share/locale/*/LC_MESSAGES/zoitechat.mo
usr/share/metainfo/net.zoite.Zoitechat.appdata.xml
usr/share/mime/packages/net.zoite.Zoitechat.mime.xml

View File

@@ -1,2 +0,0 @@
usr/include/zoitechat-plugin.h
usr/lib/*/pkgconfig/zoitechat-plugin.pc

View File

@@ -1 +0,0 @@
usr/lib/*/zoitechat/plugins/lua.so

View File

@@ -1 +0,0 @@
usr/lib/*/zoitechat/plugins/perl.so

View File

@@ -1,3 +0,0 @@
usr/lib/*/zoitechat/plugins/checksum.so
usr/lib/*/zoitechat/plugins/fishlim.so
usr/lib/*/zoitechat/plugins/sysinfo.so

View File

@@ -1,5 +0,0 @@
usr/lib/*/zoitechat/plugins/python.so
usr/lib/*/zoitechat/python/_zoitechat.py
usr/lib/*/zoitechat/python/hexchat.py
usr/lib/*/zoitechat/python/xchat.py
usr/lib/*/zoitechat/python/zoitechat.py

View File

@@ -1 +0,0 @@
dh_installchangelogs

View File

@@ -1,2 +0,0 @@
usr/bin/zoitechat
usr/share/man/man1/zoitechat.1

View File

@@ -1,6 +0,0 @@
# intentional typo as example for autoreplace function
zoitechat: spelling-error-in-binary usr/bin/zoitechat teh the
# upstream will not correct misspelled variable names
zoitechat: spelling-error-in-binary usr/bin/zoitechat hilight highlight
# fixing this spelling error would break scripting/theming
zoitechat: spelling-error-in-binary usr/bin/zoitechat Conection Connection

View File

@@ -6,6 +6,4 @@ rm -f *.app.zip
python $HOME/.local/bin/gtk-mac-bundler zoitechat.bundle
echo "Compressing bundle"
#hdiutil create -format UDBZ -srcdir ZoiteChat.app -quiet ZoiteChat-2.9.6.1-$(git rev-parse --short master).dmg
zip -9rXq ./ZoiteChat-$(git describe --tags).app.zip ./ZoiteChat.app

View File

@@ -26,7 +26,7 @@
#include "zoitechat-plugin.h"
static zoitechat_plugin *ph; /* plugin handle */
static zoitechat_plugin *ph;
static char name[] = "Checksum";
static char desc[] = "Calculate checksum for DCC file transfers";
static char version[] = "4.0";
@@ -42,18 +42,14 @@ typedef struct {
static void
print_sha256_result (ChecksumCallbackInfo *info, const char *checksum, const char *filename, GError *error)
{
// So then we get the next best available channel, since we always want to print at least somewhere, it's fine
zoitechat_context *ctx = zoitechat_find_context(ph, info->servername, info->channel);
if (!ctx) {
// before we print a private message to the wrong channel, we exit early
if (info->send_message) {
return;
}
// if the context isn't found the first time, we search in the server
ctx = zoitechat_find_context(ph, info->servername, NULL);
if (!ctx) {
// The second time we exit early, since printing in another server isn't desireable
return;
}
}

View File

@@ -25,7 +25,7 @@
#include "zoitechat-plugin.h"
static zoitechat_plugin *ph; /* plugin handle */
static zoitechat_plugin *ph;
static char name[] = "Exec";
static char desc[] = "Execute commands inside ZoiteChat";
static char version[] = "1.2";
@@ -71,7 +71,7 @@ run_command (char *word[], char *word_eol[], void *userdata)
strcat (commandLine, word_eol[2]);
}
CreatePipe (&readPipe, &writePipe, &secattr, 0); /* might be replaced with MyCreatePipeEx */
CreatePipe (&readPipe, &writePipe, &secattr, 0);
ZeroMemory (&sInfo, sizeof (sInfo));
ZeroMemory (&pInfo, sizeof (pInfo));
@@ -91,12 +91,10 @@ run_command (char *word[], char *word_eol[], void *userdata)
{
if (ReadFile (readPipe, buffer, sizeof (buffer) - 1, &dwRead, NULL) && dwRead != 0 )
{
/* avoid garbage */
buffer[dwRead] = '\0';
if (announce)
{
/* Say each line seperately, TODO: improve... */
token = strtok_s (buffer, "\n", &context);
while (token != NULL)
{
@@ -110,13 +108,11 @@ run_command (char *word[], char *word_eol[], void *userdata)
}
else
{
/* this way we'll more likely get full lines */
SleepEx (100, TRUE);
}
timeElapsed = difftime (time (0), start);
}
/* display a newline to separate things */
if (!announce)
zoitechat_printf (ph, "\n");
@@ -149,7 +145,7 @@ zoitechat_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name, char
zoitechat_hook_command (ph, "EXEC", ZOITECHAT_PRI_NORM, run_command, "Usage: /EXEC [-O] - execute commands inside ZoiteChat", 0);
zoitechat_printf (ph, "%s plugin loaded\n", name);
return 1; /* return 1 for success */
return 1;
}
int

View File

@@ -39,13 +39,11 @@ gboolean irc_parse_message(const char *words[],
if (prefix) *prefix = NULL;
if (command) *command = NULL;
/* See if the message starts with a prefix (sender user) */
if (words[w][0] == ':') {
if (prefix) *prefix = &words[w][1];
w++;
}
/* Check command */
if (words[w][0] == '\0') return FALSE;
if (command) *command = words[w];
w++;
@@ -72,11 +70,9 @@ char *irc_prefix_get_nick(const char *prefix) {
if (!prefix) return NULL;
/* Find end of nick */
end = prefix;
while (*end != '\0' && *end != '!' && *end != '@') end++;
/* Allocate string */
length = end - prefix;
return g_strndup (prefix, length);
}

View File

@@ -277,15 +277,6 @@ char *decrypt_raw_message(const char *message, const char *key) {
return NULL;
}
/*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
zoitechat_printf(ph, "debug incoming: ");
for (size_t i = 1; word[i] != NULL && word[i][0] != '\0'; i++) {
zoitechat_printf(ph, ">%s< ", word[i]);
}
zoitechat_printf(ph, "\n");
return ZOITECHAT_EAT_NONE;
}*/
/**
* Called when a message is to be sent.
*/
@@ -811,7 +802,6 @@ int zoitechat_plugin_init(zoitechat_plugin *plugin_handle,
zoitechat_hook_server(ph, "NOTICE", ZOITECHAT_PRI_HIGHEST, handle_keyx_notice, NULL);
zoitechat_hook_server_attrs(ph, "NOTICE", ZOITECHAT_PRI_NORM, handle_incoming, NULL);
zoitechat_hook_server_attrs(ph, "PRIVMSG", ZOITECHAT_PRI_NORM, handle_incoming, NULL);
/* zoitechat_hook_server(ph, "RAW LINE", ZOITECHAT_PRI_NORM, handle_debug, NULL); */
zoitechat_hook_server_attrs(ph, "TOPIC", ZOITECHAT_PRI_NORM, handle_incoming, NULL);
zoitechat_hook_server_attrs(ph, "332", ZOITECHAT_PRI_NORM, handle_incoming, NULL);
@@ -836,4 +826,3 @@ int zoitechat_plugin_deinit(void) {
zoitechat_printf(ph, "%s plugin unloaded\n", plugin_name);
return 1;
}

View File

@@ -440,8 +440,6 @@ server_cb (char *word[], char *word_eol[], void *userdata)
if (data->depth)
return ZOITECHAT_EAT_NONE;
/* zoitechat_printf (ph, */
/* "Received %d words in server callback", av_len (wd)); */
PUSHMARK (SP);
XPUSHs (newRV_noinc ((SV *) array2av (word)));
XPUSHs (newRV_noinc ((SV *) array2av (word_eol)));
@@ -489,8 +487,6 @@ command_cb (char *word[], char *word_eol[], void *userdata)
if (data->depth)
return ZOITECHAT_EAT_NONE;
/* zoitechat_printf (ph, "Received %d words in command callback", */
/* av_len (wd)); */
PUSHMARK (SP);
XPUSHs (newRV_noinc ((SV *) array2av (word)));
XPUSHs (newRV_noinc ((SV *) array2av (word_eol)));
@@ -567,7 +563,6 @@ print_cb (char *word[], void *userdata)
}
}
/*zoitechat_printf (ph, "Received %d words in print callback", av_len (wd)+1); */
PUSHMARK (SP);
XPUSHs (newRV_noinc ((SV *) wd));
XPUSHs (data->userdata);

View File

@@ -79,7 +79,6 @@ def emit_print(event_name, *args, **kwargs):
return ret
# TODO: this shadows itself. command should be changed to cmd
def command(command):
lib.zoitechat_command(lib.ph, command.encode())
@@ -221,7 +220,6 @@ def get_list(name):
return ret
# TODO: 'command' here shadows command above, and should be renamed to cmd
def hook_command(command, callback, userdata=None, priority=PRI_NORM, help=None):
plugin = __get_current_plugin()
hook = plugin.add_hook(callback, userdata)

View File

@@ -5,11 +5,9 @@ import cffi
builder = cffi.FFI()
# zoitechat-plugin.h
with open(sys.argv[1]) as f:
output = []
eat_until_endif = 0
# This is very specific to zoitechat-plugin.h, it is not a cpp
for line in f:
if line.startswith('#define'):
continue
@@ -81,9 +79,7 @@ int zoitechat_plugin_deinit(void)
}
''')
# python.py
with open(sys.argv[2]) as f:
builder.embedding_init_code(f.read())
# python.c
builder.emit_c_code(sys.argv[3])

View File

@@ -19,12 +19,11 @@ else:
if not hasattr(sys, 'argv'):
sys.argv = ['<zoitechat>']
VERSION = b'2.18.0~pre2' # Sync with zoitechat.__version__
VERSION = b'2.18.0~pre2'
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_VERSION = ffi.new('char[]', VERSION)
# TODO: Constants should be screaming snake case
zoitechat = None
local_interp = None
zoitechat_stdout = None
@@ -106,8 +105,6 @@ if sys.version_info[0] == 2:
return compile(string, '<string>', 'eval', dont_inherit=True)
except SyntaxError:
# For some reason `print` is invalid for eval
# This will hide any return value though
return compile(string, '<string>', 'exec', dont_inherit=True)
else:
def compile_file(data, filename):
@@ -115,7 +112,6 @@ else:
def compile_line(string):
# newline appended to solve unexpected EOF issues
return compile(string + '\n', '<string>', 'single', optimize=2, dont_inherit=True)
@@ -200,8 +196,6 @@ else:
return string.decode()
# There can be empty entries between non-empty ones so find the actual last value
def _cstr(ptr):
"""Safely convert a C char* (possibly NULL) to bytes."""
if ptr == ffi.NULL:
@@ -212,7 +206,6 @@ def _cstr(ptr):
return b''
def wordlist_len(words):
# ZoiteChat passes a fixed-size array (typically 32) where unused entries may be NULL.
for i in range(31, 0, -1):
if _cstr(words[i]):
return i
@@ -299,12 +292,8 @@ def _on_timer_hook(userdata):
return 1
try:
# Avoid calling zoitechat_unhook twice if unnecessary
hook.is_unload = True
except ReferenceError:
# hook is a weak reference, it might have been destroyed by the callback
# in which case it has already been removed from hook.plugin.hooks and
# we wouldn't be able to test it with h == hook anyway.
return 0
for h in hook.plugin.hooks:
@@ -338,11 +327,9 @@ def _on_say_command(word, word_eol, userdata):
if not python:
return 1
# Dont let exceptions here swallow core commands or wedge the UI.
try:
exec_in_interp(python)
except Exception:
# Best effort: surface the traceback in the python tab.
exc = traceback.format_exc().encode('utf-8', errors='replace')
lib.zoitechat_print(lib.ph, exc)
return 1
@@ -397,11 +384,10 @@ def autoload():
configdir = __decode(_cstr(lib.zoitechat_get_info(lib.ph, b'configdir')))
addondir = os.path.join(configdir, 'addons')
try:
with change_cwd(addondir): # Maintaining old behavior
with change_cwd(addondir):
for f in os.listdir(addondir):
if f.endswith('.py'):
log('Autoloading', f)
# TODO: Set cwd
load_filename(os.path.join(addondir, f))
except FileNotFoundError as e:

View File

@@ -208,7 +208,6 @@ sysinfo_cb (char *word[], char *word_eol[], void *userdata)
int offset = 0, channel_type;
char *cmd;
/* Allow overriding global announce setting */
if (!strcmp ("-e", word[2]))
{
announce = FALSE;
@@ -220,7 +219,6 @@ sysinfo_cb (char *word[], char *word_eol[], void *userdata)
offset++;
}
/* Cannot send to server tab */
channel_type = zoitechat_list_int (ph, NULL, "type");
if (channel_type != 2 /* SESS_CHANNEL */ && channel_type != 3 /* SESS_DIALOG */)
announce = FALSE;
@@ -246,7 +244,6 @@ zoitechat_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name, char
zoitechat_hook_command (ph, "SYSINFO", ZOITECHAT_PRI_NORM, sysinfo_cb, sysinfo_help, NULL);
/* Match the classic label from HexChat so people can actually find it. */
zoitechat_command (ph, "MENU ADD \"Window/Display System Info\" \"SYSINFO\"");
zoitechat_printf (ph, _("%s plugin loaded\n"), name);
return 1;
@@ -255,7 +252,6 @@ zoitechat_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name, char
int
zoitechat_plugin_deinit (void)
{
/* Keep both in case older builds used a different label. */
zoitechat_command (ph, "MENU DEL \"Window/Send System Info\"");
zoitechat_command (ph, "MENU DEL \"Window/Display System Info\"");
zoitechat_printf (ph, _("%s plugin unloaded\n"), name);

View File

@@ -132,7 +132,6 @@ void pci_find_fullname(char *fullname, char *vendor, char *device)
if(fp == NULL)
{
g_snprintf(fullname, bsize, "%s:%s", vendor, device);
//sysinfo_print_error ("pci.ids file not found! You might want to adjust your pciids setting with /SYSINFO SET pciids (you can query its current value with /SYSINFO LIST).\n");
return;
}

View File

@@ -26,7 +26,7 @@
#define APPCAST_URL "https://zoitechat.zoite.net/appcast.xml"
static zoitechat_plugin *ph; /* plugin handle */
static zoitechat_plugin *ph;
static char name[] = "Update Checker";
static char desc[] = "Check for ZoiteChat updates automatically";
static char version[] = "5.0";

View File

@@ -20,7 +20,7 @@
#define PLAYING 1
#define PAUSED 3
static zoitechat_plugin *ph; /* plugin handle */
static zoitechat_plugin *ph;
static int
winamp(char *word[], char *word_eol[], void *userdata)
@@ -130,7 +130,6 @@ zoitechat_plugin_init(zoitechat_plugin *plugin_handle,
char **plugin_version,
char *arg)
{
/* we need to save this for use with any zoitechat_* functions */
ph = plugin_handle;
*plugin_name = "Winamp";
@@ -142,7 +141,7 @@ zoitechat_plugin_init(zoitechat_plugin *plugin_handle,
zoitechat_print (ph, "Winamp plugin loaded\n");
return 1; /* return 1 for success */
return 1;
}
int

View File

@@ -1,10 +1,10 @@
<div align="center">
<img src="data/icons/zoitechat.svg" height="230">
[![Debian Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/debian-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/debian-build.yml)
[![Flatpak Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/flatpak-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/flatpak-build.yml)
[![AppImage Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/appimage-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/appimage-build.yml)
[![Windows Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/windows-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/windows-build.yml)
[![Manjaro Package Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/manjaro-package-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/manjaro-package-build.yml)
[![Version][github-version-img]][github-version-uri] [![Downloads][github-downloads-img]][github-downloads-uri] [![Size][github-size-img]][github-size-img] [![Last Commit][github-commit-img]][github-commit-img] [![Contributors][contribs-all-img]](#contributors-)

View File

@@ -419,6 +419,7 @@ const struct prefs vars[] =
{"gui_input_nick", P_OFFINT (hex_gui_input_nick), TYPE_BOOL},
{"gui_input_spell", P_OFFINT (hex_gui_input_spell), TYPE_BOOL},
{"gui_input_style", P_OFFINT (hex_gui_input_style), TYPE_BOOL},
{"gui_gtk3_theme_name", P_OFFSET (hex_gui_gtk3_theme_name), TYPE_STR},
{"gui_join_dialog", P_OFFINT (hex_gui_join_dialog), TYPE_BOOL},
{"gui_lagometer", P_OFFINT (hex_gui_lagometer), TYPE_INT},
{"gui_lang", P_OFFINT (hex_gui_lang), TYPE_INT},
@@ -764,7 +765,6 @@ load_default_config(void)
prefs.hex_gui_input_style = 1;
prefs.hex_gui_join_dialog = 1;
prefs.hex_gui_quit_dialog = 1;
/* prefs.hex_gui_slist_skip = 1; */
prefs.hex_gui_tab_chans = 1;
prefs.hex_gui_tab_dialogs = 1;
prefs.hex_gui_tab_icons = 1;
@@ -788,7 +788,7 @@ load_default_config(void)
prefs.hex_irc_reconnect_rejoin = 1;
prefs.hex_irc_cap_server_time = 1;
prefs.hex_irc_logging = 1;
prefs.hex_irc_who_join = 1; /* Can kick with inordinate amount of channels, required for some of our features though, TODO: add cap like away check? */
prefs.hex_irc_who_join = 1;
prefs.hex_irc_whois_front = 1;
prefs.hex_net_auto_reconnect = 1;
prefs.hex_net_throttle = 1;
@@ -819,7 +819,7 @@ load_default_config(void)
prefs.hex_flood_ctcp_num = 5;
prefs.hex_flood_ctcp_time = 30;
prefs.hex_flood_msg_num = 5;
/*FIXME*/ prefs.hex_flood_msg_time = 30;
prefs.hex_flood_msg_time = 30;
prefs.hex_gui_chanlist_maxusers = 9999;
prefs.hex_gui_chanlist_minusers = 5;
prefs.hex_gui_dialog_height = 256;

View File

@@ -99,8 +99,6 @@ str_to_chanopt (const char *str)
return SET_DEFAULT;
}
/* handle the /CHANOPT command */
int
chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
{
@@ -135,13 +133,13 @@ chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
{
if (find[0] == 0 || match (find, chanopt[i].name) || (chanopt[i].alias && match (find, chanopt[i].alias)))
{
if (newval != -1) /* set new value */
if (newval != -1)
{
*(guint8 *)G_STRUCT_MEMBER_P(sess, chanopt[i].offset) = newval;
chanopt_changed = TRUE;
}
if (!quiet) /* print value */
if (!quiet)
{
strcpy (tbuf, chanopt[i].name);
p = strlen (tbuf);
@@ -177,18 +175,13 @@ chanopt_is_set (unsigned int global, guint8 per_chan_setting)
return global;
}
/* === below is LOADING/SAVING stuff only === */
typedef struct
{
/* Per-Channel Alerts */
/* use a byte, because we need a pointer to each element */
guint8 alert_balloon;
guint8 alert_beep;
guint8 alert_taskbar;
guint8 alert_tray;
/* Per-Channel Settings */
guint8 text_hidejoinpart;
guint8 text_logging;
guint8 text_scrollback;
@@ -218,12 +211,10 @@ chanopt_find (char *network, char *channel, gboolean add_new)
if (!add_new)
return NULL;
/* allocate a new one */
co = g_new0 (chanopt_in_memory, 1);
co->channel = g_strdup (channel);
co->network = g_strdup (network);
/* set all values to SET_DEFAULT */
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
@@ -254,8 +245,6 @@ chanopt_add_opt (chanopt_in_memory *co, char *var, int new_value)
}
}
/* load chanopt.conf from disk into our chanopt_list GSList */
static void
chanopt_load_all (void)
{
@@ -265,7 +254,6 @@ chanopt_load_all (void)
char *network = NULL;
chanopt_in_memory *current = NULL;
/* 1. load the old file into our GSList */
fh = zoitechat_open_file ("chanopt.conf", O_RDONLY, 0, 0);
if (fh != -1)
{
@@ -326,7 +314,6 @@ chanopt_load (session *sess)
if (!co)
return;
/* fill in all the sess->xxxxx fields */
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
@@ -352,8 +339,6 @@ chanopt_save (session *sess)
if (!network)
return;
/* 2. reconcile sess with what we loaded from disk */
co = chanopt_find (network, sess->session_name, TRUE);
i = 0;

View File

@@ -743,9 +743,6 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
EMIT_SIGNAL (XP_TE_DCCRECVERR, dcc->serv->front_session, dcc->file,
dcc->destfile, dcc->nick,
errorstring ((n < 0) ? sock_error () : 0), 0);
/* send ack here? but the socket is dead */
/*if (need_ack)
dcc_send_ack (dcc);*/
dcc_close (dcc, STAT_FAILED, FALSE);
return TRUE;
}
@@ -1383,7 +1380,6 @@ dcc_connect (struct DCC *dcc)
dcc_close (dcc, STAT_FAILED, FALSE);
return;
}
/* possible problems with filenames containing spaces? */
if (dcc->type == TYPE_RECV)
g_snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" :
@@ -1660,17 +1656,14 @@ dcc_listen_init (struct DCC *dcc, session *sess)
SAddr.sin_family = AF_INET;
/*if local_ip is specified use that*/
if (prefs.local_ip != 0xffffffff)
{
my_addr = prefs.local_ip;
SAddr.sin_addr.s_addr = prefs.local_ip;
}
/*otherwise use the default*/
else
my_addr = SAddr.sin_addr.s_addr;
/*if we have a valid portrange try to use that*/
if (prefs.hex_dcc_port_first > 0)
{
SAddr.sin_port = 0;
@@ -1680,7 +1673,6 @@ dcc_listen_init (struct DCC *dcc, session *sess)
{
SAddr.sin_port = htons (prefs.hex_dcc_port_first + i);
i++;
/*printf("Trying to bind against port: %d\n",ntohs(SAddr.sin_port));*/
bindretval = bind (dcc->sok, (struct sockaddr *) &SAddr, sizeof (SAddr));
}
@@ -1707,12 +1699,8 @@ dcc_listen_init (struct DCC *dcc, session *sess)
dcc->port = ntohs (SAddr.sin_port);
/*if we have a dcc_ip, we use that, so the remote client can connect*/
/*else we try to take an address from hex_dcc_ip*/
/*if something goes wrong we tell the client to connect to our LAN ip*/
dcc->addr = dcc_get_my_address (sess);
/*if nothing else worked we use the address we bound to*/
if (dcc->addr == 0)
dcc->addr = my_addr;
@@ -1728,7 +1716,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
}
static struct session *dccsess;
static char *dccto; /* lame!! */
static char *dccto;
static gint64 dccmaxcps;
static int recursive = FALSE;

View File

@@ -153,8 +153,6 @@ ignore_showlist (session *sess)
strcat (tbuf, _("NO "));
strcat (tbuf, "\n");
PrintText (sess, tbuf);
/*EMIT_SIGNAL (XP_TE_IGNORELIST, sess, ig->mask, 0, 0, 0, 0); */
/* use this later, when TE's support 7 args */
list = list->next;
}
@@ -413,4 +411,3 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what) /*0=ct
}
return 1;
}

View File

@@ -108,7 +108,6 @@ find_session_from_nick (char *nick, server *serv)
if (serv->front_session)
{
// If we are here for ChanServ, then it is usually a reply for the user
if (!g_ascii_strcasecmp(nick, "ChanServ") || userlist_find (serv->front_session, nick))
return serv->front_session;
}
@@ -2121,7 +2120,6 @@ scram_authenticate (server *serv, const char *data, const char *digest,
if (status == SCRAM_IN_PROGRESS)
{
// Authentication is still in progress
encoded = g_base64_encode ((guchar *) output, output_len);
tcp_sendf (serv, "AUTHENTICATE %s\r\n", encoded);
g_free (encoded);
@@ -2129,13 +2127,11 @@ scram_authenticate (server *serv, const char *data, const char *digest,
}
else if (status == SCRAM_SUCCESS)
{
// Authentication succeeded
tcp_sendf (serv, "AUTHENTICATE +\r\n");
g_clear_pointer (&serv->scram_session, scram_session_free);
}
else if (status == SCRAM_ERROR)
{
// Authentication failed
tcp_sendf (serv, "AUTHENTICATE *\r\n");
if (serv->scram_session->error != NULL)

View File

@@ -96,11 +96,6 @@ textevents = custom_target('textevents',
command: [make_te, '@INPUT@', '@OUTPUT0@', '@OUTPUT1@']
)
# TODO:
# LOOKUPD
# SIGACTION
# HAVE_GTK_MAC
if libssl_dep.found()
common_sources += 'ssl.c'
common_deps += libssl_dep

View File

@@ -87,7 +87,7 @@ notify_do_network (struct notify *notify, server *serv)
return TRUE;
if (token_foreach (notify->networks, ',', notify_netcmp, serv))
return FALSE; /* network list doesn't contain this one */
return FALSE;
return TRUE;
}
@@ -106,8 +106,6 @@ notify_find_server_entry (struct notify *notify, struct server *serv)
list = list->next;
}
/* not found, should we add it, or is this not a network where
we're monitoring this nick? */
if (!notify_do_network (notify, serv))
return NULL;
@@ -123,11 +121,7 @@ notify_save (void)
{
int fh;
struct notify *notify;
// while reading the notify.conf file, elements are added by prepending to the
// list. reverse the list before writing to disk to keep the original
// order of the list
GSList *list = g_slist_copy(notify_list);
list = g_slist_reverse(list);
GSList *list = g_slist_reverse (g_slist_copy (notify_list));
fh = zoitechat_open_file ("notify.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
if (fh != -1)
@@ -146,7 +140,7 @@ notify_save (void)
}
close (fh);
}
g_slist_free(list);
g_slist_free (list);
}
void

View File

@@ -42,19 +42,16 @@ struct notify_per_server
extern GSList *notify_list;
extern int notify_tag;
/* the WATCH stuff */
void notify_set_online (server * serv, char *nick,
const message_tags_data *tags_data);
void notify_set_offline (server * serv, char *nick, int quiet,
const message_tags_data *tags_data);
/* the MONITOR stuff */
const message_tags_data *tags_data);
void notify_set_online_list (server * serv, char *users,
const message_tags_data *tags_data);
void notify_set_offline_list (server * serv, char *users, int quiet,
const message_tags_data *tags_data);
const message_tags_data *tags_data);
void notify_send_watches (server * serv);
/* the general stuff */
void notify_adduser (char *name, char *networks);
int notify_deluser (char *name);
void notify_cleanup (void);
@@ -65,7 +62,6 @@ gboolean notify_is_in_list (server *serv, char *name);
int notify_isnotify (session *sess, char *name);
struct notify_per_server *notify_find_server_entry (struct notify *notify, struct server *serv);
/* the old ISON stuff - remove me? */
void notify_markonline (server *serv, char *word[],
const message_tags_data *tags_data);
int notify_checklist (void);

View File

@@ -3774,37 +3774,29 @@ cmd_url (struct session *sess, char *tbuf, char *word[], char *word_eol[])
if (zoitechat_theme_path_from_arg (word[2], &theme_path))
{
GError *error = NULL;
char *basename = g_path_get_basename (theme_path);
char *dot = strrchr (basename, '.');
char *message;
char *theme_name = NULL;
if (dot)
*dot = '\0';
if (zoitechat_import_theme (theme_path, &error))
if (zoitechat_import_gtk3_theme_archive (theme_path, &theme_name, &error))
{
if (zoitechat_apply_theme (basename, &error))
if (theme_name)
{
message = g_strdup_printf (_("Theme \"%s\" imported and applied."), basename);
char *message = g_strdup_printf (_("GTK3 theme \"%s\" imported. Use Theme settings to apply it."), theme_name);
fe_message (message, FE_MSG_INFO);
handle_command (sess, "gui apply", FALSE);
g_free (message);
}
else
{
fe_message (error ? error->message : _("Theme imported, but failed to apply."),
FE_MSG_ERROR);
g_clear_error (&error);
fe_message (_("GTK3 theme imported. Use Theme settings to apply it."), FE_MSG_INFO);
}
}
else
{
fe_message (error ? error->message : _("Failed to import theme."),
fe_message (error ? error->message : _("Failed to import GTK3 theme archive."),
FE_MSG_ERROR);
g_clear_error (&error);
}
g_free (basename);
g_free (theme_name);
g_free (theme_path);
return TRUE;
}

View File

@@ -30,7 +30,7 @@
#define _(x) zoitechat_gettext(ph,x)
static zoitechat_plugin *ph; /* plugin handle */
static zoitechat_plugin *ph;
static GSList *timer_list = NULL;
#define STATIC
@@ -146,7 +146,6 @@ timer_showlist (void)
zoitechat_print (ph, _(HELP));
return;
}
/* 00000 00000000 0000000 abc */
zoitechat_print (ph, _("\026 Ref# Seconds Repeat Command \026\n"));
list = timer_list;
while (list)
@@ -218,7 +217,6 @@ zoitechat_plugin_init
(zoitechat_plugin *plugin_handle, char **plugin_name,
char **plugin_desc, char **plugin_version, char *arg)
{
/* we need to save this for use with any zoitechat_* functions */
ph = plugin_handle;
*plugin_name = "Timer";
@@ -227,5 +225,5 @@ zoitechat_plugin_init
zoitechat_hook_command (ph, "TIMER", ZOITECHAT_PRI_NORM, timer_cb, _(HELP), 0);
return 1; /* return 1 for success */
return 1;
}

View File

@@ -28,7 +28,6 @@
#define CLIENT_KEY "Client Key"
#define SERVER_KEY "Server Key"
// EVP_MD_CTX_create() and EVP_MD_CTX_destroy() were renamed in OpenSSL 1.1.0
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
#define EVP_MD_CTX_new(ctx) EVP_MD_CTX_create(ctx)
#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy(ctx)
@@ -46,7 +45,6 @@ scram_session
if (md == NULL)
{
// Unknown message digest
return NULL;
}
@@ -189,7 +187,6 @@ process_server_first (scram_session *session, const char *data, char **output,
client_nonce_len = strlen (session->client_nonce_b64);
// The server can append his nonce to the client's nonce
if (strlen (server_nonce_b64) < client_nonce_len ||
strncmp (server_nonce_b64, session->client_nonce_b64, client_nonce_len))
{
@@ -199,28 +196,22 @@ process_server_first (scram_session *session, const char *data, char **output,
g_base64_decode_inplace ((gchar *) salt, &salt_len);
// SaltedPassword := Hi(Normalize(password), salt, i)
session->salted_password = g_malloc (session->digest_size);
PKCS5_PBKDF2_HMAC (session->password, strlen (session->password), (unsigned char *) salt,
salt_len, iteration_count, session->digest, session->digest_size,
session->salted_password);
// AuthMessage := client-first-message-bare + "," +
// server-first-message + "," +
// client-final-message-without-proof
client_final_message_without_proof = g_strdup_printf ("c=biws,r=%s", server_nonce_b64);
session->auth_message = g_strdup_printf ("%s,%s,%s", session->client_first_message_bare,
data, client_final_message_without_proof);
// ClientKey := HMAC(SaltedPassword, "Client Key")
client_key = g_malloc0 (session->digest_size);
HMAC (session->digest, session->salted_password, session->digest_size,
(unsigned char *) CLIENT_KEY, strlen (CLIENT_KEY), client_key, &client_key_len);
// StoredKey := H(ClientKey)
if (!create_SHA (session, client_key, session->digest_size, stored_key, &stored_key_len))
{
g_free (client_final_message_without_proof);
@@ -230,12 +221,10 @@ process_server_first (scram_session *session, const char *data, char **output,
return SCRAM_ERROR;
}
// ClientSignature := HMAC(StoredKey, AuthMessage)
client_signature = g_malloc0 (session->digest_size);
HMAC (session->digest, stored_key, stored_key_len, (unsigned char *) session->auth_message,
strlen ((char *) session->auth_message), client_signature, NULL);
// ClientProof := ClientKey XOR ClientSignature
client_proof = g_malloc0 (client_key_len);
for (i = 0; i < client_key_len; i++)
@@ -276,12 +265,10 @@ process_server_final (scram_session *session, const char *data)
verifier = g_strdup (data + 2);
g_base64_decode_inplace (verifier, &verifier_len);
// ServerKey := HMAC(SaltedPassword, "Server Key")
server_key = g_malloc0 (session->digest_size);
HMAC (session->digest, session->salted_password, session->digest_size,
(unsigned char *) SERVER_KEY, strlen (SERVER_KEY), server_key, &server_key_len);
// ServerSignature := HMAC(ServerKey, AuthMessage)
server_signature = g_malloc0 (session->digest_size);
HMAC (session->digest, server_key, session->digest_size,
(unsigned char *) session->auth_message, strlen ((char *) session->auth_message),
@@ -330,4 +317,4 @@ scram_process (scram_session *session, const char *input, char **output, size_t
return status;
}
#endif
#endif

View File

@@ -510,16 +510,7 @@ server_stopconnecting (server * serv)
static void
ssl_cb_info (SSL * s, int where, int ret)
{
/* char buf[128];*/
return; /* FIXME: make debug level adjustable in serverlist or settings */
/* g_snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
if (g_sess)
EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
else
fprintf (stderr, "%s\n", buf);*/
}
static int
@@ -625,14 +616,6 @@ ssl_do_connect (server * serv)
cert_info.algorithm, cert_info.algorithm_bits);
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
NULL, 0);
/*if (cert_info.rsa_tmp_bits)
{
g_snprintf (buf, sizeof (buf),
" Public key algorithm uses ephemeral key with %d bits",
cert_info.rsa_tmp_bits);
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
NULL, 0);
}*/
g_snprintf (buf, sizeof (buf), " Sign algorithm %s",
cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
@@ -675,8 +658,6 @@ ssl_do_connect (server * serv)
}
break;
}
/* g_snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
@@ -1870,11 +1851,9 @@ server_set_defaults (server *serv)
char *
server_get_network (server *serv, gboolean fallback)
{
/* check the network list */
if (serv->network)
return ((ircnet *)serv->network)->name;
/* check the network name given in 005 NETWORK=... */
if (serv->server_session && *serv->server_session->channel)
return serv->server_session->channel;
@@ -1893,7 +1872,6 @@ server_set_name (server *serv, char *name)
if (name[0] == 0)
name = serv->hostname;
/* strncpy parameters must NOT overlap */
if (name != serv->servername)
{
safe_strcpy (serv->servername, name, sizeof (serv->servername));

View File

@@ -1065,7 +1065,7 @@ servlist_load (void)
}
}
if (buf[0] == 'N')
net = servlist_net_add (buf + 2, /* comment */ NULL, FALSE);
net = servlist_net_add (buf + 2, NULL, FALSE);
}
fclose (fp);

View File

@@ -125,8 +125,4 @@ GSList *servlist_favchan_listadd (GSList *chanlist, char *channel, char *key);
gboolean joinlist_is_in_list (server *serv, char *channel);
/* FIXME
void joinlist_split (char *autojoin, GSList **channels, GSList **keys);
void joinlist_free (GSList *channels, GSList *keys);
*/
#endif

View File

@@ -465,7 +465,6 @@ static char *read_hdd_info (IWbemClassObject *object)
if (name_len >= 4 && name_bstr[0] == L'\\' && name_bstr[1] == L'\\' && name_bstr[2] == L'?' && name_bstr[3] == L'\\')
{
// This is not a named volume. Skip it.
VariantClear (&name_variant);
return NULL;

View File

@@ -95,7 +95,6 @@ url_save_node (char* url)
{
FILE *fd;
/* open <config>/url.log in append mode */
fd = zoitechat_fopen_file ("url.log", "a", 0);
if (fd == NULL)
{
@@ -118,7 +117,6 @@ url_add (char *urltext, int len)
char *data;
int size;
/* we don't need any URLs if we have neither URL grabbing nor URL logging enabled */
if (!prefs.hex_url_grabber && !prefs.hex_url_logging)
{
return;
@@ -126,12 +124,11 @@ url_add (char *urltext, int len)
data = g_strndup (urltext, len);
if (data[len - 1] == '.') /* chop trailing dot */
if (data[len - 1] == '.')
{
len--;
data[len] = 0;
}
/* chop trailing ) but only if there's no counterpart */
if (data[len - 1] == ')' && strchr (data, '(') == NULL)
{
data[len - 1] = 0;
@@ -142,7 +139,6 @@ url_add (char *urltext, int len)
url_save_node (data);
}
/* the URL is saved already, only continue if we need the URL grabber too */
if (!prefs.hex_url_grabber)
{
g_free (data);
@@ -162,11 +158,8 @@ url_add (char *urltext, int len)
}
size = tree_size (url_tree);
/* 0 is unlimited */
if (prefs.hex_url_grabber_limit > 0 && size >= prefs.hex_url_grabber_limit)
{
/* the loop is necessary to handle having the limit lowered while
ZoiteChat is running */
size -= prefs.hex_url_grabber_limit;
for(; size > 0; size--)
{
@@ -183,10 +176,6 @@ url_add (char *urltext, int len)
fe_url_add (data);
}
/* check if a word is clickable. This is called on mouse motion events, so
keep it FAST! This new version was found to be almost 3x faster than
2.4.4 release. */
static int laststart = 0;
static int lastend = 0;
static int lasttype = 0;
@@ -234,7 +223,6 @@ match_nick (const char *word, int *start, int *end)
if (!regex_match (re_nick (), word, start, end))
return FALSE;
/* ignore matches with prefixes that the server doesn't use */
if (strchr (NICKPRE, word[*start])
&& !strchr (nick_prefixes, word[*start]))
return FALSE;

View File

@@ -169,13 +169,12 @@ errorstring (int err)
return tbuf;
}
}
} /* ! if (osvi.dwMajorVersion >= 5) */
}
/* fallback to error number */
sprintf (tbuf, "%s %d", _("Error"), err);
return tbuf;
} /* ! if (err >= WSABASEERR) */
#endif /* ! WIN32 */
}
#endif
return strerror (err);
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,14 +24,16 @@
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <time.h> /* need time_t */
#include <time.h>
#ifndef ZOITECHAT_H
#define ZOITECHAT_H
gboolean zoitechat_theme_path_from_arg (const char *arg, char **path_out);
gboolean zoitechat_import_theme (const char *path, GError **error);
gboolean zoitechat_apply_theme (const char *theme_name, GError **error);
/* Imports a GTK3 theme archive into ZoiteChat's own gtk3-themes store. */
gboolean zoitechat_import_gtk3_theme_archive (const char *archive_path,
char **theme_name_out,
GError **error);
#ifdef USE_OPENSSL
#ifdef __APPLE__
@@ -44,11 +46,11 @@ gboolean zoitechat_apply_theme (const char *theme_name, GError **error);
#include "tree.h"
#ifdef USE_OPENSSL
#include <openssl/ssl.h> /* SSL_() */
#include <openssl/ssl.h>
#include "scram.h"
#endif
#ifdef __EMX__ /* for o/s 2 */
#ifdef __EMX__
#define OFLAGS O_BINARY
#define g_ascii_strcasecmp stricmp
#define g_ascii_strncasecmp strnicmp
@@ -59,7 +61,7 @@ gboolean zoitechat_apply_theme (const char *theme_name, GError **error);
/* force a 32bit CMP.L */
#define WORDL(c0, c1, c2, c3) (guint32)(c0 | (c1 << 8) | (c2 << 16) | (c3 << 24))
#ifdef WIN32 /* for win32 */
#ifdef WIN32
#define OFLAGS O_BINARY
#define sleep(t) Sleep(t*1000)
#include <direct.h>
@@ -71,7 +73,7 @@ gboolean zoitechat_apply_theme (const char *theme_name, GError **error);
#define S_ISDIR(m) ((m) & _S_IFDIR)
#endif
#define NETWORK_PRIVATE
#else /* for unix */
#else
#define OFLAGS 0
#endif
@@ -295,6 +297,7 @@ struct zoitechatprefs
char hex_dcc_completed_dir[PATHLEN + 1];
char hex_dcc_dir[PATHLEN + 1];
char hex_dcc_ip[DOMAINLEN + 1];
char hex_gui_gtk3_theme_name[128];
char hex_gui_ulist_doubleclick[256];
char hex_input_command_char[4];
char hex_irc_extra_hilight[300];

View File

@@ -562,7 +562,10 @@ banlist_clear (GtkWidget * wid, banlist_info *banl)
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
_("Are you sure you want to remove all listed items in %s?"), banl->sess->channel);
_("Are you sure you want to remove all listed items in %s?"), banl->sess->channel);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (banlist_clear_cb), banl);

View File

@@ -190,11 +190,11 @@ tab_scroll_left_up_clicked (GtkWidget *widget, chanview *cv)
gtk_adjustment_set_value (adj, new_value);
tab_left_is_moving = 0; /* hSP: set to false in case we didnt get stopped (the normal case) */
tab_left_is_moving = 0;
}
else
{
tab_left_is_moving = 0; /* hSP: jump directly to next element if user is clicking faster than we can scroll.. */
tab_left_is_moving = 0;
}
}
@@ -239,11 +239,11 @@ tab_scroll_right_down_clicked (GtkWidget *widget, chanview *cv)
gtk_adjustment_set_value (adj, new_value);
tab_right_is_moving = 0; /* hSP: set to false in case we didnt get stopped (the normal case) */
tab_right_is_moving = 0;
}
else
{
tab_right_is_moving = 0; /* hSP: jump directly to next element if user is clicking faster than we can scroll.. */
tab_right_is_moving = 0;
}
}
@@ -332,7 +332,6 @@ cv_tabs_init (chanview *cv)
((tabview *)cv)->outer = outer;
g_signal_connect (G_OBJECT (outer), "size_allocate",
G_CALLBACK (cv_tabs_sizealloc), cv);
/* gtk_container_set_border_width (GTK_CONTAINER (outer), 2);*/
gtk_widget_show (outer);
viewport = gtk_viewport_new (0, 0);
@@ -574,7 +573,7 @@ tab_pressed_cb (GtkToggleButton *tab, chan *ch)
ignore_toggle = FALSE;
cv->focused = ch;
if (/*tab->active*/is_switching)
if (is_switching)
/* call the focus callback */
cv->cb_focus (cv, ch, ch->tag, ch->userdata);
}

View File

@@ -127,15 +127,15 @@ chanview_apply_theme (chanview *cv)
if (input_style)
font = input_style->font_desc;
if (fe_dark_mode_is_enabled () || prefs.hex_gui_dark_mode == ZOITECHAT_DARK_MODE_LIGHT)
{
gtkutil_apply_palette (w, &colors[COL_BG], &colors[COL_FG], font);
}
else
{
/* Keep list font in sync while reverting colors to theme defaults. */
gtkutil_apply_palette (w, NULL, NULL, font);
}
/*
* setup_apply_to_sess() and palette_apply_dark_mode() treat all dark-mode
* preference modes as palette-driven: dark uses curated dark colors, while
* light/auto-light use the user's saved palette.
*
* Keep chanview aligned with that resolved behavior so AUTO doesn't
* accidentally revert to theme defaults and clear custom colors.
*/
gtkutil_apply_palette (w, &colors[COL_BG], &colors[COL_FG], font);
}
static char *

View File

@@ -19,6 +19,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "fe-gtk.h"
@@ -105,6 +106,9 @@ create_msg_dialog (gchar *title, gchar *message)
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s", message);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_window_set_title (GTK_WINDOW (dialog), title);
/* On Win32 we automatically have the icon. If we try to load it explicitly, it will look ugly for some reason. */
@@ -406,7 +410,12 @@ fe_args (int argc, char *argv[])
/* of the exe. */
{
g_free (win32_argv0_dir);
win32_argv0_dir = g_path_get_dirname (argv[0]);
/* In subsystem:windows builds, argv can be absent/invalid depending on
* launch context (e.g. shell URL handlers). Prefer the module path,
* then only fall back to argv[0] when it is available. */
win32_argv0_dir = g_win32_get_package_installation_directory_of_module (NULL);
if (win32_argv0_dir == NULL && argc > 0 && argv != NULL && argv[0] != NULL)
win32_argv0_dir = g_path_get_dirname (argv[0]);
if (win32_argv0_dir)
chdir (win32_argv0_dir);
}
@@ -537,10 +546,13 @@ static gboolean
fe_system_prefers_dark (void)
{
GtkSettings *settings = gtk_settings_get_default ();
gboolean theme_name_prefers_dark = FALSE;
gboolean property_prefers_dark = FALSE;
gboolean prefer_dark = FALSE;
char *theme_name = NULL;
#ifdef G_OS_WIN32
gboolean have_win_pref = FALSE;
gboolean win_prefers_dark = FALSE;
if (fe_win32_high_contrast_is_enabled ())
return FALSE;
@@ -549,37 +561,336 @@ fe_system_prefers_dark (void)
if (!settings)
return FALSE;
#ifdef G_OS_WIN32
have_win_pref = fe_win32_try_get_system_dark (&prefer_dark);
if (!have_win_pref)
#endif
g_object_get (settings, "gtk-theme-name", &theme_name, NULL);
if (theme_name)
{
char *lower = g_ascii_strdown (theme_name, -1);
if (g_str_has_suffix (lower, "-dark") || g_strrstr (lower, "dark"))
theme_name_prefers_dark = TRUE;
g_free (lower);
g_free (theme_name);
}
if (g_object_class_find_property (G_OBJECT_GET_CLASS (settings),
"gtk-application-prefer-dark-theme"))
{
g_object_get (settings, "gtk-application-prefer-dark-theme", &prefer_dark, NULL);
/* Even if we last wrote this property, the toolkit or desktop can update
* it later, so AUTO mode should keep reading it as a signal. */
g_object_get (settings, "gtk-application-prefer-dark-theme", &property_prefers_dark, NULL);
}
if (!prefer_dark)
{
g_object_get (settings, "gtk-theme-name", &theme_name, NULL);
if (theme_name)
{
char *lower = g_ascii_strdown (theme_name, -1);
if (g_str_has_suffix (lower, "-dark") || g_strrstr (lower, "dark"))
prefer_dark = TRUE;
g_free (lower);
g_free (theme_name);
}
}
#ifdef G_OS_WIN32
have_win_pref = fe_win32_try_get_system_dark (&win_prefers_dark);
#endif
/* Deterministic precedence: any explicit dark signal wins. */
prefer_dark = theme_name_prefers_dark || property_prefers_dark;
#ifdef G_OS_WIN32
prefer_dark = prefer_dark || (have_win_pref && win_prefers_dark);
#endif
return prefer_dark;
}
static gboolean auto_dark_mode_enabled = FALSE;
static gboolean dark_mode_state_initialized = FALSE;
static gboolean
fe_parse_gtk3_minor_from_dirname (const char *name, gint *minor_out)
{
const char *prefix = "gtk-3.";
char *endptr = NULL;
long value;
if (!name || !g_str_has_prefix (name, prefix))
return FALSE;
value = strtol (name + strlen (prefix), &endptr, 10);
if (endptr == name + strlen (prefix) || *endptr != '\0' || value < 0 || value > G_MAXINT)
return FALSE;
if (minor_out)
*minor_out = (gint) value;
return TRUE;
}
gboolean
fe_resolve_gtk3_theme_dir (const char *theme_root,
char **gtk3_dir_out,
gboolean *has_dark_css_out)
{
GDir *dir;
const char *entry;
gint runtime_minor = gtk_get_minor_version ();
gint best_minor = -1;
gint best_distance = G_MAXINT;
char *best_dir = NULL;
gboolean has_dark = FALSE;
if (gtk3_dir_out)
*gtk3_dir_out = NULL;
if (has_dark_css_out)
*has_dark_css_out = FALSE;
if (!theme_root || !*theme_root)
return FALSE;
dir = g_dir_open (theme_root, 0, NULL);
if (!dir)
return FALSE;
while ((entry = g_dir_read_name (dir)) != NULL)
{
char *candidate_dir;
char *gtk_css;
char *gtk_dark_css;
gint minor;
gint distance;
if (!fe_parse_gtk3_minor_from_dirname (entry, &minor))
continue;
candidate_dir = g_build_filename (theme_root, entry, NULL);
if (!g_file_test (candidate_dir, G_FILE_TEST_IS_DIR))
{
g_free (candidate_dir);
continue;
}
gtk_css = g_build_filename (candidate_dir, "gtk.css", NULL);
if (!g_file_test (gtk_css, G_FILE_TEST_IS_REGULAR))
{
g_free (gtk_css);
g_free (candidate_dir);
continue;
}
g_free (gtk_css);
distance = (minor <= runtime_minor)
? (runtime_minor - minor)
: (10000 + (minor - runtime_minor));
if (!best_dir || distance < best_distance || (distance == best_distance && minor > best_minor))
{
g_free (best_dir);
best_dir = candidate_dir;
best_minor = minor;
best_distance = distance;
gtk_dark_css = g_build_filename (best_dir, "gtk-dark.css", NULL);
has_dark = g_file_test (gtk_dark_css, G_FILE_TEST_IS_REGULAR);
g_free (gtk_dark_css);
candidate_dir = NULL;
}
g_free (candidate_dir);
}
g_dir_close (dir);
if (!best_dir)
return FALSE;
if (gtk3_dir_out)
*gtk3_dir_out = g_strdup (best_dir);
if (has_dark_css_out)
*has_dark_css_out = has_dark;
g_free (best_dir);
return TRUE;
}
static GtkCssProvider *gtk3_theme_provider = NULL;
static char *gtk3_theme_provider_name = NULL;
static gboolean gtk3_theme_provider_dark = FALSE;
static GResource *gtk3_theme_resource = NULL;
static char *gtk3_theme_resource_path = NULL;
#ifdef G_OS_WIN32
static void fe_apply_windows_theme (gboolean dark);
#endif
static void
fe_apply_windows_theme (gboolean dark)
fe_gtk3_theme_unregister_resource (void)
{
if (gtk3_theme_resource)
{
g_resources_unregister (gtk3_theme_resource);
g_clear_pointer (&gtk3_theme_resource, g_resource_unref);
}
g_clear_pointer (&gtk3_theme_resource_path, g_free);
}
static gboolean
fe_gtk3_theme_register_resource (const char *resource_path, GError **error)
{
GResource *resource;
if (!resource_path || !*resource_path)
{
fe_gtk3_theme_unregister_resource ();
return TRUE;
}
if (gtk3_theme_resource && gtk3_theme_resource_path
&& g_strcmp0 (gtk3_theme_resource_path, resource_path) == 0)
return TRUE;
resource = g_resource_load (resource_path, error);
if (!resource)
return FALSE;
fe_gtk3_theme_unregister_resource ();
g_resources_register (resource);
gtk3_theme_resource = resource;
gtk3_theme_resource_path = g_strdup (resource_path);
return TRUE;
}
gboolean
fe_apply_gtk3_theme_with_reload (const char *theme_name, gboolean force_reload, GError **error)
{
GdkScreen *screen = gdk_screen_get_default ();
char *theme_dir = NULL;
char *gtk3_dir = NULL;
char *gtk_css = NULL;
char *gtk_dark_css = NULL;
char *gtk_resource = NULL;
const char *selected_css = NULL;
gboolean dark = fe_dark_mode_is_enabled ();
GList *toplevels, *node;
if (!theme_name || !*theme_name)
{
#ifdef G_OS_WIN32
/* Keep the Win32 fallback provider in sync when returning to the
* system theme from Preferences > Themes. */
fe_apply_windows_theme (dark);
#endif
if (gtk3_theme_provider && screen)
{
gtk_style_context_remove_provider_for_screen (
screen,
GTK_STYLE_PROVIDER (gtk3_theme_provider));
gtk_style_context_reset_widgets (screen);
}
g_clear_object (&gtk3_theme_provider);
g_clear_pointer (&gtk3_theme_provider_name, g_free);
gtk3_theme_provider_dark = FALSE;
fe_gtk3_theme_unregister_resource ();
toplevels = gtk_window_list_toplevels ();
for (node = toplevels; node; node = node->next)
fe_apply_theme_to_toplevel (GTK_WIDGET (node->data));
g_list_free (toplevels);
return TRUE;
}
if (!force_reload
&& gtk3_theme_provider_name
&& g_strcmp0 (gtk3_theme_provider_name, theme_name) == 0
&& gtk3_theme_provider_dark == dark)
{
return TRUE;
}
theme_dir = g_build_filename (get_xdir (), "gtk3-themes", theme_name, NULL);
if (!fe_resolve_gtk3_theme_dir (theme_dir, &gtk3_dir, NULL))
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
_("GTK3 theme '%s' is missing a valid gtk-3.x/gtk.css directory."), theme_name);
g_free (theme_dir);
return FALSE;
}
gtk_css = g_build_filename (gtk3_dir, "gtk.css", NULL);
gtk_dark_css = g_build_filename (gtk3_dir, "gtk-dark.css", NULL);
gtk_resource = g_build_filename (gtk3_dir, "gtk.gresource", NULL);
if (dark && g_file_test (gtk_dark_css, G_FILE_TEST_IS_REGULAR))
selected_css = gtk_dark_css;
else
selected_css = gtk_css;
if (g_file_test (gtk_resource, G_FILE_TEST_IS_REGULAR))
{
if (!fe_gtk3_theme_register_resource (gtk_resource, error))
{
g_free (gtk_resource);
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk3_dir);
g_free (theme_dir);
return FALSE;
}
}
else
{
fe_gtk3_theme_unregister_resource ();
}
if (!gtk3_theme_provider)
gtk3_theme_provider = gtk_css_provider_new ();
if (!gtk_css_provider_load_from_path (gtk3_theme_provider, selected_css, error))
{
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk_resource);
g_free (gtk3_dir);
g_free (theme_dir);
return FALSE;
}
if (screen)
{
gtk_style_context_add_provider_for_screen (
screen,
GTK_STYLE_PROVIDER (gtk3_theme_provider),
/* Use user priority so imported GTK3 themes can also override
* ZoiteChat's own application CSS (for example, button backgrounds). */
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_style_context_reset_widgets (screen);
}
#ifdef G_OS_WIN32
/* Applying a GTK3 theme should immediately disable ZoiteChat's Win32
* fallback window CSS so buttons/chat widgets are fully theme-driven. */
fe_apply_windows_theme (dark);
#endif
g_free (gtk3_theme_provider_name);
gtk3_theme_provider_name = g_strdup (theme_name);
gtk3_theme_provider_dark = dark;
toplevels = gtk_window_list_toplevels ();
for (node = toplevels; node; node = node->next)
fe_apply_theme_to_toplevel (GTK_WIDGET (node->data));
g_list_free (toplevels);
g_free (gtk_dark_css);
g_free (gtk_css);
g_free (gtk_resource);
g_free (gtk3_dir);
g_free (theme_dir);
return TRUE;
}
gboolean
fe_apply_gtk3_theme (const char *theme_name, GError **error)
{
return fe_apply_gtk3_theme_with_reload (theme_name, FALSE, error);
}
static void
fe_set_gtk_prefer_dark_theme (gboolean dark)
{
GtkSettings *settings = gtk_settings_get_default ();
@@ -588,24 +899,94 @@ fe_apply_windows_theme (gboolean dark)
{
g_object_set (settings, "gtk-application-prefer-dark-theme", dark, NULL);
}
}
#ifdef G_OS_WIN32
static void
fe_append_window_theme_class_css (GString *css,
const char *class_name,
const PaletteColor *fg,
const PaletteColor *bg)
{
char *fg_css = gdk_rgba_to_string (fg);
char *bg_css = gdk_rgba_to_string (bg);
g_string_append_printf (css,
"window.%s, .%s {"
"background-color: %s;"
"color: %s;"
"}"
"window.%s button, .%s button, window.%s entry, .%s entry, "
"window.%s treeview, .%s treeview, window.%s scrolledwindow, .%s scrolledwindow {"
"background-color: %s;"
"color: %s;"
"}",
class_name,
class_name,
class_name,
class_name,
class_name,
class_name,
class_name,
class_name,
class_name,
class_name,
bg_css,
fg_css);
g_free (fg_css);
g_free (bg_css);
}
static void
fe_apply_windows_theme (gboolean dark)
{
static GtkCssProvider *win_theme_provider = NULL;
fe_set_gtk_prefer_dark_theme (dark);
{
static GtkCssProvider *win_theme_provider = NULL;
GdkScreen *screen = gdk_screen_get_default ();
const char *css =
"window.zoitechat-dark, .zoitechat-dark {"
"background-color: #202020;"
"color: #f0f0f0;"
"}"
"window.zoitechat-light, .zoitechat-light {"
"background-color: #f6f6f6;"
"color: #101010;"
"}";
const PaletteColor *light_palette = palette_user_colors ();
const PaletteColor *dark_palette = palette_dark_colors ();
GString *css;
/* Let imported GTK3 themes own all widget/window colors on Windows.
* Otherwise ZoiteChat's fallback dark/light window background CSS can
* clash with theme widget colors (for example white buttons on a dark
* window background).
*
* Use the active provider state (not only the configured preference): if
* a configured theme fails to load we still want fallback palette CSS so
* the app keeps a coherent dark/light appearance on Windows releases.
*/
if (gtk3_theme_provider != NULL)
{
if (win_theme_provider && screen)
{
gtk_style_context_remove_provider_for_screen (
screen,
GTK_STYLE_PROVIDER (win_theme_provider));
gtk_style_context_reset_widgets (screen);
}
return;
}
css = g_string_new (NULL);
if (!win_theme_provider)
win_theme_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (win_theme_provider, css, -1, NULL);
fe_append_window_theme_class_css (css,
"zoitechat-dark",
&dark_palette[COL_FG],
&dark_palette[COL_BG]);
fe_append_window_theme_class_css (css,
"zoitechat-light",
&light_palette[COL_FG],
&light_palette[COL_BG]);
gtk_css_provider_load_from_data (win_theme_provider, css->str, -1, NULL);
g_string_free (css, TRUE);
if (screen)
gtk_style_context_add_provider_for_screen (
screen,
@@ -640,6 +1021,13 @@ void
fe_set_auto_dark_mode_state (gboolean enabled)
{
auto_dark_mode_enabled = enabled;
dark_mode_state_initialized = TRUE;
}
gboolean
fe_dark_mode_state_is_initialized (void)
{
return dark_mode_state_initialized;
}
void
@@ -652,6 +1040,11 @@ gboolean
fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed)
{
gboolean enabled = fe_dark_mode_is_enabled_for (mode);
GList *toplevels, *node;
/* Apply the optional global GTK preference first, then reapply palette-driven
* chat/input colors so Preferences > Colors continues to take precedence. */
fe_set_gtk_prefer_dark_theme (enabled);
gboolean changed = palette_apply_dark_mode (enabled);
#ifdef G_OS_WIN32
@@ -664,30 +1057,42 @@ fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed)
if (input_style)
create_input_style (input_style);
if (!fe_apply_gtk3_theme (prefs.hex_gui_gtk3_theme_name, NULL)
&& prefs.hex_gui_gtk3_theme_name[0] != '\0')
{
fe_message (_("Failed to apply configured GTK3 theme from gtk3-themes."), FE_MSG_ERROR);
}
/* Existing toplevel windows also need the class refreshed for selectors like
* .zoitechat-dark / .zoitechat-light to update immediately. */
toplevels = gtk_window_list_toplevels ();
for (node = toplevels; node; node = node->next)
fe_apply_theme_to_toplevel (GTK_WIDGET (node->data));
g_list_free (toplevels);
return enabled;
}
void
fe_apply_theme_to_toplevel (GtkWidget *window)
{
GtkStyleContext *context;
gboolean dark;
if (!window)
return;
#ifdef G_OS_WIN32
context = gtk_widget_get_style_context (window);
dark = fe_dark_mode_is_enabled ();
if (context)
{
GtkStyleContext *context = gtk_widget_get_style_context (window);
gboolean dark = fe_dark_mode_is_enabled ();
if (context)
{
gtk_style_context_remove_class (context, "zoitechat-dark");
gtk_style_context_remove_class (context, "zoitechat-light");
gtk_style_context_add_class (context, dark ? "zoitechat-dark" : "zoitechat-light");
}
gtk_style_context_remove_class (context, "zoitechat-dark");
gtk_style_context_remove_class (context, "zoitechat-light");
gtk_style_context_add_class (context, dark ? "zoitechat-dark" : "zoitechat-light");
}
#endif
fe_win32_apply_native_titlebar (window, fe_dark_mode_is_enabled ());
fe_win32_apply_native_titlebar (window, dark);
}
gboolean
@@ -727,6 +1132,12 @@ create_input_style (InputStyle *style)
static guint16 last_bg_red;
static guint16 last_bg_green;
static guint16 last_bg_blue;
static guint16 last_sel_fg_red;
static guint16 last_sel_fg_green;
static guint16 last_sel_fg_blue;
static guint16 last_sel_bg_red;
static guint16 last_sel_bg_green;
static guint16 last_sel_bg_blue;
if (!style)
style = g_new0 (InputStyle, 1);
@@ -758,6 +1169,12 @@ create_input_style (InputStyle *style)
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;
gboolean dark_mode = fe_dark_mode_is_enabled ();
gboolean needs_reload;
@@ -765,6 +1182,8 @@ create_input_style (InputStyle *style)
palette_color_get_rgb16 (&colors[COL_FG], &fg_red, &fg_green, &fg_blue);
palette_color_get_rgb16 (&colors[COL_BG], &bg_red, &bg_green, &bg_blue);
palette_color_get_rgb16 (&colors[COL_MARK_FG], &sel_fg_red, &sel_fg_green, &sel_fg_blue);
palette_color_get_rgb16 (&colors[COL_MARK_BG], &sel_bg_red, &sel_bg_green, &sel_bg_blue);
needs_reload = !done_rc
|| !last_input_style
|| last_dark_mode != dark_mode
@@ -775,7 +1194,13 @@ create_input_style (InputStyle *style)
|| last_fg_blue != fg_blue
|| last_bg_red != bg_red
|| last_bg_green != bg_green
|| last_bg_blue != bg_blue;
|| last_bg_blue != bg_blue
|| last_sel_fg_red != sel_fg_red
|| last_sel_fg_green != sel_fg_green
|| last_sel_fg_blue != sel_fg_blue
|| last_sel_bg_red != sel_bg_red
|| last_sel_bg_green != sel_bg_green
|| last_sel_bg_blue != sel_bg_blue;
if (needs_reload)
{
@@ -799,28 +1224,107 @@ create_input_style (InputStyle *style)
}
{
GString *css = g_string_new ("#zoitechat-inputbox {");
GtkWidget *tmp_entry = NULL;
GtkStyleContext *tmp_context = NULL;
GdkRGBA selected_fg = { 0.0, 0.0, 0.0, 1.0 };
GdkRGBA selected_bg = { 0.0, 0.0, 0.0, 1.0 };
gboolean have_palette_selected_colors;
const char *selection_fg_css = NULL;
const char *selection_bg_css = NULL;
char selection_fg_hex[8];
char selection_bg_hex[8];
char *selection_fg_fallback = NULL;
char *selection_bg_fallback = NULL;
/* GTK3 equivalents for adwaita_workaround_rc/cursor_color_rc. */
if (adwaita_workaround_rc[0] != '\0'
&& theme_name
&& (g_str_has_prefix (theme_name, "Adwaita")
|| g_str_has_prefix (theme_name, "Yaru")))
g_string_append (css, "background-image: none;");
have_palette_selected_colors =
isfinite (colors[COL_MARK_FG].red)
&& isfinite (colors[COL_MARK_FG].green)
&& isfinite (colors[COL_MARK_FG].blue)
&& isfinite (colors[COL_MARK_BG].red)
&& isfinite (colors[COL_MARK_BG].green)
&& isfinite (colors[COL_MARK_BG].blue);
if (have_palette_selected_colors)
{
g_snprintf (selection_fg_hex, sizeof (selection_fg_hex), "#%02x%02x%02x",
(sel_fg_red >> 8), (sel_fg_green >> 8), (sel_fg_blue >> 8));
g_snprintf (selection_bg_hex, sizeof (selection_bg_hex), "#%02x%02x%02x",
(sel_bg_red >> 8), (sel_bg_green >> 8), (sel_bg_blue >> 8));
selection_fg_css = selection_fg_hex;
selection_bg_css = selection_bg_hex;
}
else
{
tmp_entry = gtk_entry_new ();
tmp_context = tmp_entry ? gtk_widget_get_style_context (tmp_entry) : NULL;
if (tmp_context)
{
if (!gtk_style_context_lookup_color (
tmp_context,
"theme_selected_fg_color",
&selected_fg))
selected_fg = colors[COL_MARK_FG];
if (!gtk_style_context_lookup_color (
tmp_context,
"theme_selected_bg_color",
&selected_bg))
selected_bg = colors[COL_MARK_BG];
}
else
{
selected_fg = colors[COL_MARK_FG];
selected_bg = colors[COL_MARK_BG];
}
selection_fg_fallback = gdk_rgba_to_string (&selected_fg);
selection_bg_fallback = gdk_rgba_to_string (&selected_bg);
selection_fg_css = selection_fg_fallback ? selection_fg_fallback : "@theme_selected_fg_color";
selection_bg_css = selection_bg_fallback ? selection_bg_fallback : "@theme_selected_bg_color";
}
g_string_append_printf (
css,
"background-color: #%02x%02x%02x;"
"color: #%02x%02x%02x;"
"caret-color: %s;"
"}"
"#zoitechat-inputbox text {"
"color: #%02x%02x%02x;"
"caret-color: %s;"
"}"
"#zoitechat-inputbox:focus text,"
"#zoitechat-inputbox:backdrop text {"
"color: #%02x%02x%02x;"
"caret-color: %s;"
"}"
"#zoitechat-inputbox:disabled text {"
"color: alpha(#%02x%02x%02x, 0.7);"
"}"
"#zoitechat-inputbox text selection {"
"color: %s;"
"background-color: %s;"
"}",
(bg_red >> 8), (bg_green >> 8), (bg_blue >> 8),
cursor_color,
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8),
cursor_color,
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8),
cursor_color);
cursor_color,
(fg_red >> 8), (fg_green >> 8), (fg_blue >> 8),
selection_fg_css,
selection_bg_css);
if (tmp_entry)
gtk_widget_destroy (tmp_entry);
g_clear_pointer (&selection_fg_fallback, g_free);
g_clear_pointer (&selection_bg_fallback, g_free);
gtk_css_provider_load_from_data (input_css_provider, css->str, -1, NULL);
g_string_free (css, TRUE);
}
@@ -841,6 +1345,12 @@ create_input_style (InputStyle *style)
last_bg_red = bg_red;
last_bg_green = bg_green;
last_bg_blue = bg_blue;
last_sel_fg_red = sel_fg_red;
last_sel_fg_green = sel_fg_green;
last_sel_fg_blue = sel_fg_blue;
last_sel_bg_red = sel_bg_red;
last_sel_bg_green = sel_bg_green;
last_sel_bg_blue = sel_bg_blue;
g_free (last_theme_name);
last_theme_name = g_strdup (theme_name);
}
@@ -876,7 +1386,10 @@ fe_init (void)
palette_load ();
settings = gtk_settings_get_default ();
if (settings)
{
auto_dark_mode_enabled = fe_system_prefers_dark ();
dark_mode_state_initialized = TRUE;
}
fe_apply_theme_for_mode (prefs.hex_gui_dark_mode, NULL);
key_init ();
@@ -925,8 +1438,6 @@ fe_main (void)
void
fe_cleanup (void)
{
/* it's saved when pressing OK in setup.c */
/*palette_save ();*/
}
void
@@ -963,8 +1474,7 @@ log_handler (const gchar *log_domain,
{
session *sess;
/* if (getenv ("ZOITECHAT_WARNING_IGNORE")) this gets ignored sometimes, so simply just disable all warnings */
return;
return;
sess = find_dialog (serv_list->data, "(warnings)");
if (!sess)
@@ -977,8 +1487,6 @@ log_handler (const gchar *log_domain,
#endif
/* install tray stuff */
static int
fe_idle (gpointer data)
{
@@ -1044,7 +1552,10 @@ fe_message (char *msg, int flags)
type = GTK_MESSAGE_INFO;
dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), 0, type,
GTK_BUTTONS_OK, "%s", msg);
GTK_BUTTONS_OK, "%s", msg);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
if (flags & FE_MSG_MARKUP)
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
g_signal_connect (G_OBJECT (dialog), "response",
@@ -1445,6 +1956,9 @@ fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
mg_detach (sess, arg); /* arg: 0=toggle 1=detach 2=attach */
break;
case FE_GUI_APPLY:
/* Keep parity with Preferences -> Theme apply path (setup_theme_apply_cb). */
palette_load ();
fe_apply_theme_for_mode (prefs.hex_gui_dark_mode, NULL);
setup_apply_real (TRUE, TRUE, TRUE, FALSE);
}
}

View File

@@ -189,9 +189,16 @@ extern cairo_surface_t *dialogwin_pix;
gboolean fe_dark_mode_is_enabled (void);
gboolean fe_dark_mode_is_enabled_for (unsigned int mode);
gboolean fe_dark_mode_state_is_initialized (void);
void fe_set_auto_dark_mode_state (gboolean enabled);
void fe_refresh_auto_dark_mode (void);
gboolean fe_apply_theme_for_mode (unsigned int mode, gboolean *palette_changed);
gboolean fe_apply_gtk3_theme (const char *theme_name, GError **error);
gboolean fe_apply_gtk3_theme_with_reload (const char *theme_name, gboolean force_reload,
GError **error);
gboolean fe_resolve_gtk3_theme_dir (const char *theme_root,
char **gtk3_dir_out,
gboolean *has_dark_css_out);
void fe_apply_theme_to_toplevel (GtkWidget *window);
#define SPELL_ENTRY_GET_TEXT(e) ((char *)(gtk_entry_get_text (GTK_ENTRY(e))))

View File

@@ -1199,11 +1199,6 @@ corrupt_file:
return 5;
}
/* ***** Key actions start here *********** */
/* See the NOTES above --AGL */
/* "Run command" */
static int
key_action_handle_command (GtkWidget * wid, GdkEventKey * evt, char *d1,
char *d2, struct session *sess)
@@ -1224,7 +1219,6 @@ key_action_handle_command (GtkWidget * wid, GdkEventKey * evt, char *d1,
/*
* Check if the given session is inside the main window. This predicate
* is passed to lastact_getfirst() as a way to filter out detached sessions.
* XXX: Consider moving this in a different file?
*/
static int
session_check_is_tab(session *sess)
@@ -1806,7 +1800,7 @@ key_action_move_tab_left (GtkWidget * wid, GdkEventKey * ent, char *d1,
char *d2, struct session *sess)
{
mg_move_tab (sess, +1);
return 2; /* don't allow default action */
return 2;
}
static int
@@ -1814,7 +1808,7 @@ key_action_move_tab_right (GtkWidget * wid, GdkEventKey * ent, char *d1,
char *d2, struct session *sess)
{
mg_move_tab (sess, -1);
return 2; /* -''- */
return 2;
}
static int
@@ -1822,7 +1816,7 @@ key_action_move_tab_family_left (GtkWidget * wid, GdkEventKey * ent, char *d1,
char *d2, struct session *sess)
{
mg_move_tab_family (sess, +1);
return 2; /* don't allow default action */
return 2;
}
static int
@@ -1830,7 +1824,7 @@ key_action_move_tab_family_right (GtkWidget * wid, GdkEventKey * ent, char *d1,
char *d2, struct session *sess)
{
mg_move_tab_family (sess, -1);
return 2; /* -''- */
return 2;
}
static int
@@ -1839,12 +1833,9 @@ key_action_put_history (GtkWidget * wid, GdkEventKey * ent, char *d1,
{
history_add (&sess->history, SPELL_ENTRY_GET_TEXT (wid));
SPELL_ENTRY_SET_TEXT (wid, "");
return 2; /* -''- */
return 2;
}
/* -------- */
static void
replace_handle (GtkWidget *t)
{

View File

@@ -163,28 +163,6 @@ gtkutil_menu_custom_icon_from_icon_name (const char *icon_name)
}
static GdkPixbuf *
gtkutil_menu_icon_pixbuf_new (const char *icon_name)
{
GdkPixbuf *pixbuf = NULL;
char *resource_path;
if (!icon_name || !g_str_has_prefix (icon_name, "zc-menu-"))
return NULL;
resource_path = g_strdup_printf ("/icons/menu/light/%s.png", icon_name + strlen ("zc-menu-"));
pixbuf = gdk_pixbuf_new_from_resource (resource_path, NULL);
if (!pixbuf)
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/light/%s.svg", icon_name + strlen ("zc-menu-"));
pixbuf = gdk_pixbuf_new_from_resource (resource_path, NULL);
}
g_free (resource_path);
return pixbuf;
}
const char *
gtkutil_icon_name_from_stock (const char *stock_name)
{
@@ -251,6 +229,11 @@ gtkutil_menu_icon_theme_variant (void)
char *theme_name_lower = NULL;
const char *theme_variant = "light";
/* Prefer ZoiteChat's explicit dark-mode selection when available so icon
* variants stay in sync with the app mode, not only the system theme. */
if (fe_dark_mode_state_is_initialized () || prefs.hex_gui_dark_mode != ZOITECHAT_DARK_MODE_AUTO)
return fe_dark_mode_is_enabled () ? "dark" : "light";
settings = gtk_settings_get_default ();
if (settings)
{
@@ -269,41 +252,68 @@ gtkutil_menu_icon_theme_variant (void)
return theme_variant;
}
static char *
gtkutil_menu_icon_resource_path (const char *icon_name, const char *extension)
{
char *resource_path;
const char *variant;
if (!icon_name || !extension || !g_str_has_prefix (icon_name, "zc-menu-"))
return NULL;
variant = gtkutil_menu_icon_theme_variant ();
resource_path = g_strdup_printf ("/icons/menu/%s/%s.%s", variant,
icon_name + strlen ("zc-menu-"), extension);
if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/light/%s.%s",
icon_name + strlen ("zc-menu-"), extension);
if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
{
g_free (resource_path);
return NULL;
}
}
return resource_path;
}
gboolean
gtkutil_menu_icon_exists (const char *icon_name)
{
char *resource_path;
gboolean found;
resource_path = gtkutil_menu_icon_resource_path (icon_name, "png");
if (!resource_path)
resource_path = gtkutil_menu_icon_resource_path (icon_name, "svg");
found = resource_path != NULL;
g_free (resource_path);
return found;
}
static GtkWidget *
gtkutil_menu_icon_image_new (const char *icon_name, GtkIconSize size)
{
GtkWidget *image = NULL;
GdkPixbuf *pixbuf = NULL;
char *resource_path;
const char *variant;
if (!icon_name || !g_str_has_prefix (icon_name, "zc-menu-"))
return NULL;
resource_path = gtkutil_menu_icon_resource_path (icon_name, "png");
if (!resource_path)
resource_path = gtkutil_menu_icon_resource_path (icon_name, "svg");
variant = gtkutil_menu_icon_theme_variant ();
resource_path = g_strdup_printf ("/icons/menu/%s/%s.png", variant, icon_name + strlen ("zc-menu-"));
if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
if (resource_path)
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/light/%s.png", icon_name + strlen ("zc-menu-"));
}
pixbuf = gdk_pixbuf_new_from_resource (resource_path, NULL);
if (!pixbuf)
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/%s/%s.svg", variant, icon_name + strlen ("zc-menu-"));
if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL))
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/light/%s.svg", icon_name + strlen ("zc-menu-"));
}
pixbuf = gdk_pixbuf_new_from_resource (resource_path, NULL);
}
if (pixbuf)
{
image = gtk_image_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
if (pixbuf)
{
image = gtk_image_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
}
}
g_free (resource_path);
@@ -327,20 +337,19 @@ gtkutil_image_new_from_stock (const char *stock, GtkIconSize size)
{
GtkWidget *image;
const char *icon_name;
const char *custom_icon_name;
icon_name = gtkutil_icon_name_from_stock (stock);
if (!icon_name && stock && g_str_has_prefix (stock, "zc-menu-"))
icon_name = stock;
if (size == GTK_ICON_SIZE_MENU)
{
const char *menu_icon_name = gtkutil_menu_custom_icon_from_stock (stock);
if (!menu_icon_name)
menu_icon_name = gtkutil_menu_custom_icon_from_icon_name (icon_name);
if (menu_icon_name)
icon_name = menu_icon_name;
}
/* Use ZoiteChat's themed icon resources consistently across menu and button
* images so dark/light mode swaps all app icons together. */
custom_icon_name = gtkutil_menu_custom_icon_from_stock (stock);
if (!custom_icon_name)
custom_icon_name = gtkutil_menu_custom_icon_from_icon_name (icon_name);
if (custom_icon_name)
icon_name = custom_icon_name;
image = gtkutil_menu_icon_image_new (icon_name, size);
if (image)
@@ -668,8 +677,6 @@ static void
gtkutil_file_req_done (GtkWidget * wid, struct file_req *freq)
{
gtkutil_file_req_done_chooser (GTK_FILE_CHOOSER (freq->dialog), freq);
/* this should call the "destroy" cb, where we free(freq) */
gtk_widget_destroy (freq->dialog);
}
@@ -682,7 +689,6 @@ gtkutil_file_req_response (GtkWidget *dialog, gint res, struct file_req *freq)
return;
}
/* this should call the "destroy" cb, where we free(freq) */
gtk_widget_destroy (dialog);
}
@@ -806,21 +812,25 @@ gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *us
if (flags & FRF_WRITE)
{
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Save"), GTK_RESPONSE_ACCEPT,
NULL);
dialog = gtk_file_chooser_dialog_new (title, effective_parent,
GTK_FILE_CHOOSER_ACTION_SAVE,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Save"), GTK_RESPONSE_ACCEPT,
NULL);
if (!(flags & FRF_NOASKOVERWRITE))
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
}
else
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
dialog = gtk_file_chooser_dialog_new (title, effective_parent,
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
if (filter && filter[0] && (flags & FRF_FILTERISINITIAL))
{
@@ -891,7 +901,8 @@ gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *us
g_signal_connect (G_OBJECT (dialog), "destroy",
G_CALLBACK (gtkutil_file_req_destroy), (gpointer) freq);
if (effective_parent)
if (effective_parent &&
gtk_window_get_transient_for (GTK_WINDOW (dialog)) != effective_parent)
gtk_window_set_transient_for (GTK_WINDOW (dialog), effective_parent);
if (flags & FRF_MODAL)
@@ -980,6 +991,9 @@ fe_get_str (char *msg, char *def, void *callback, void *userdata)
_("_Cancel"), GTK_RESPONSE_REJECT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
@@ -1075,6 +1089,9 @@ fe_get_int (char *msg, int def, void *callback, void *userdata)
_("_Cancel"), GTK_RESPONSE_REJECT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
@@ -1115,6 +1132,9 @@ fe_get_bool (char *title, char *prompt, void *callback, void *userdata)
_("_No"), GTK_RESPONSE_REJECT,
_("_Yes"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
@@ -1238,6 +1258,7 @@ gtkutil_window_new (char *title, char *role, int width, int height, int flags)
gtk_window_set_title (GTK_WINDOW (win), title);
gtk_window_set_default_size (GTK_WINDOW (win), width, height);
gtk_window_set_role (GTK_WINDOW (win), role);
fe_apply_theme_to_toplevel (win);
if (flags & 1)
gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_MOUSE);
if ((flags & 2) && parent_window)
@@ -1360,16 +1381,6 @@ gtkutil_treemodel_string_to_iter (GtkTreeModel *model, gchar *pathstr, GtkTreeIt
return success;
}
/*gboolean
gtkutil_treeview_get_selected_iter (GtkTreeView *view, GtkTreeIter *iter_ret)
{
GtkTreeModel *store;
GtkTreeSelection *select;
select = gtk_tree_view_get_selection (view);
return gtk_tree_selection_get_selected (select, &store, iter_ret);
}*/
gboolean
gtkutil_treeview_get_selected (GtkTreeView *view, GtkTreeIter *iter_ret, ...)
{

View File

@@ -41,6 +41,7 @@ GtkWidget *gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callbac
void *userdata, char *labeltext);
GtkWidget *gtkutil_image_new_from_stock (const char *stock, GtkIconSize size);
GtkWidget *gtkutil_button_new_from_stock (const char *stock, const char *label);
gboolean gtkutil_menu_icon_exists (const char *icon_name);
const char *gtkutil_icon_name_from_stock (const char *stock_name);
void gtkutil_label_new (char *text, GtkWidget * box);
GtkWidget *gtkutil_entry_new (int max, GtkWidget * box, void *callback,

View File

@@ -294,7 +294,10 @@ ignore_clear_entry_clicked (GtkWidget * wid)
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
_("Are you sure you want to remove all ignores?"));
_("Are you sure you want to remove all ignores?"));
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (ignore_clear_cb), NULL);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);

View File

@@ -81,11 +81,9 @@ joind_ok_cb (GtkWidget *ok, server *serv)
return;
}
/* do nothing */
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (serv->gui->joind_radio1)))
goto xit;
/* join specific channel */
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (serv->gui->joind_radio2)))
{
char *text = (char *)gtk_entry_get_text (GTK_ENTRY (serv->gui->joind_entry));
@@ -98,7 +96,6 @@ joind_ok_cb (GtkWidget *ok, server *serv)
goto xit;
}
/* channel list */
chanlist_opengui (serv, TRUE);
xit:
@@ -132,6 +129,9 @@ joind_show_dialog (server *serv)
char buf2[256];
serv->gui->joind_win = dialog1 = gtk_dialog_new ();
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog1);
g_snprintf(buf, sizeof(buf), _("Connection Complete - %s"), _(DISPLAY_NAME));
gtk_window_set_title (GTK_WINDOW (dialog1), buf);
gtk_window_set_type_hint (GTK_WINDOW (dialog1), GDK_WINDOW_TYPE_HINT_DIALOG);

View File

@@ -58,6 +58,87 @@
#ifdef G_OS_WIN32
#include <windows.h>
#include <shellapi.h>
#include <gdk/gdkwin32.h>
static void
mg_win32_allow_autohide_taskbar (GtkWindow *window, GdkEventWindowState *event)
{
GdkWindow *gdk_window;
HWND hwnd;
if (!window || !event)
return;
if ((event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0)
return;
gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
if (!gdk_window)
return;
hwnd = gdk_win32_window_get_handle (gdk_window);
if (!hwnd)
return;
if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
{
APPBARDATA appbar_data;
RECT work_area;
ZeroMemory (&appbar_data, sizeof (APPBARDATA));
appbar_data.cbSize = sizeof (APPBARDATA);
if ((SHAppBarMessage (ABM_GETSTATE, &appbar_data) & ABS_AUTOHIDE) != 0 &&
SHAppBarMessage (ABM_GETTASKBARPOS, &appbar_data) != 0)
{
HMONITOR monitor;
MONITORINFO monitor_info;
monitor = MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST);
ZeroMemory (&monitor_info, sizeof (MONITORINFO));
monitor_info.cbSize = sizeof (MONITORINFO);
if (monitor && GetMonitorInfo (monitor, &monitor_info))
{
work_area = monitor_info.rcMonitor;
switch (appbar_data.uEdge)
{
case ABE_LEFT:
work_area.left += 1;
break;
case ABE_TOP:
work_area.top += 1;
break;
case ABE_RIGHT:
work_area.right -= 1;
break;
case ABE_BOTTOM:
default:
work_area.bottom -= 1;
break;
}
SetWindowPos (hwnd,
NULL,
work_area.left,
work_area.top,
work_area.right - work_area.left,
work_area.bottom - work_area.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
}
SetWindowPos (hwnd,
HWND_NOTOPMOST,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
}
#endif
#define ICON_TAB_DETACH "zc-menu-detach"
@@ -659,6 +740,10 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
menu_set_fullscreen (current_sess->gui, prefs.hex_gui_win_fullscreen);
#ifdef G_OS_WIN32
mg_win32_allow_autohide_taskbar (wid, event);
#endif
return FALSE;
}
@@ -1193,7 +1278,6 @@ mg_switch_page (int relative, int num)
static void
mg_topdestroy_cb (GtkWidget *win, session *sess)
{
/* printf("enter mg_topdestroy. sess %p was destroyed\n", sess);*/
session_free (sess); /* tell zoitechat.c about it */
}
@@ -1208,7 +1292,6 @@ mg_ircdestroy (session *sess)
if (mg_gui == NULL)
{
/* puts("-> mg_gui is already NULL");*/
return;
}
@@ -1218,13 +1301,11 @@ mg_ircdestroy (session *sess)
sess = list->data;
if (sess->gui->is_tab)
{
/* puts("-> some tabs still remain");*/
return;
}
list = list->next;
}
/* puts("-> no tabs left, killing main tabwindow");*/
gtk_widget_destroy (mg_gui->window);
active_tab = NULL;
mg_gui = NULL;
@@ -1281,6 +1362,9 @@ mg_tab_close (session *sess)
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
_("This server still has %d channels or dialogs associated with it. "
"Close them all?"), i);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (mg_tab_close_cb), sess);
if (prefs.hex_gui_tab_layout)
@@ -1378,6 +1462,9 @@ mg_open_quit_dialog (gboolean minimize_button)
}
dialog = gtk_dialog_new ();
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
gtk_window_set_title (GTK_WINDOW (dialog), _("Quit ZoiteChat?"));
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
@@ -1782,7 +1869,7 @@ mg_create_tabmenu (session *sess, GdkEventButton *event, chan *ch)
if (sess)
{
char *name = g_markup_escape_text (sess->channel[0] ? sess->channel : _("<none>"), -1);
g_snprintf (buf, sizeof (buf), "<span foreground=\"#3344cc\"><b>%s</b></span>", name);
g_snprintf (buf, sizeof (buf), "<b>%s</b>", name);
g_free (name);
item = gtk_menu_item_new_with_label ("");
@@ -2004,7 +2091,6 @@ mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata)
GSList *list, *next;
session *sess;
/* puts("enter mg_tabwindow_kill_cb");*/
zoitechat_is_quitting = TRUE;
/* see if there's any non-tab windows left */
@@ -2016,7 +2102,6 @@ mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata)
if (!sess->gui->is_tab)
{
zoitechat_is_quitting = FALSE;
/* puts("-> will not exit, some toplevel windows left");*/
} else
{
mg_ircdestroy (sess);
@@ -2050,7 +2135,6 @@ mg_changui_destroy (session *sess)
/* avoid calling the "destroy" callback */
g_signal_handlers_disconnect_by_func (G_OBJECT (sess->gui->window),
mg_topdestroy_cb, sess);
/*gtk_widget_destroy (sess->gui->window);*/
/* don't destroy until the new one is created. Not sure why, but */
/* it fixes: Gdk-CRITICAL **: gdk_colormap_get_screen: */
/* assertion `GDK_IS_COLORMAP (cmap)' failed */
@@ -3603,6 +3687,8 @@ mg_create_topwindow (session *sess)
mg_place_userlist_and_chanview (sess->gui);
gtk_widget_show (win);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (win);
#ifdef G_OS_WIN32
@@ -3779,6 +3865,8 @@ mg_create_tabwindow (session *sess)
mg_place_userlist_and_chanview (sess->gui);
gtk_widget_show (win);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (win);
#ifdef G_OS_WIN32
@@ -3790,6 +3878,7 @@ mg_create_tabwindow (session *sess)
void
mg_apply_setup (void)
{
GList *toplevels, *node;
GSList *list = sess_list;
session *sess;
int done_main = FALSE;
@@ -3809,6 +3898,11 @@ mg_apply_setup (void)
done_main = TRUE;
list = list->next;
}
toplevels = gtk_window_list_toplevels ();
for (node = toplevels; node; node = node->next)
fe_apply_theme_to_toplevel (GTK_WIDGET (node->data));
g_list_free (toplevels);
}
static chan *

View File

@@ -65,28 +65,6 @@
static GSList *submenu_list;
static gboolean
menu_icon_exists_in_resource (const char *icon_name)
{
char *resource_path;
gboolean found;
if (!icon_name || !g_str_has_prefix (icon_name, "zc-menu-"))
return FALSE;
resource_path = g_strdup_printf ("/icons/menu/light/%s.png", icon_name + strlen ("zc-menu-"));
found = g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL);
if (!found)
{
g_free (resource_path);
resource_path = g_strdup_printf ("/icons/menu/light/%s.svg", icon_name + strlen ("zc-menu-"));
found = g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL, NULL, NULL);
}
g_free (resource_path);
return found;
}
static GtkWidget *
menu_icon_widget_new (const char *icon)
{
@@ -112,7 +90,7 @@ menu_icon_widget_new (const char *icon)
{
char *menu_icon_name = g_strdup_printf ("zc-menu-%s", icon);
if (menu_icon_exists_in_resource (menu_icon_name))
if (gtkutil_menu_icon_exists (menu_icon_name))
img = gtkutil_image_new_from_stock (menu_icon_name, GTK_ICON_SIZE_MENU);
else
img = gtkutil_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
@@ -1520,6 +1498,9 @@ menu_join (GtkWidget * wid, gpointer none)
_("_Cancel"), GTK_RESPONSE_REJECT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
{
GtkWidget *button;
@@ -1856,6 +1837,9 @@ static void
menu_about (GtkWidget *wid, gpointer sess)
{
GtkAboutDialog *dialog = GTK_ABOUT_DIALOG(gtk_about_dialog_new());
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark/.zoitechat-light. */
fe_apply_theme_to_toplevel (GTK_WIDGET (dialog));
char comment[512];
char *license = "This program is free software; you can redistribute it and/or modify\n" \
"it under the terms of the GNU General Public License as published by\n" \

View File

@@ -77,12 +77,6 @@ if host_machine.system() == 'windows'
zoitechat_gtk_sources += 'notifications/notification-windows.c'
zoitechat_gtk_deps += cc.find_library('dwmapi', required: true)
# TODO: mingw doesn't have these headers or libs
# add_languages('cpp')
# shared_module('hcnotifications-winrt',
# sources: 'notifications/notification-winrt.cpp'
#)
else
zoitechat_gtk_sources += 'notifications/notification-freedesktop.c'
endif
@@ -102,7 +96,7 @@ endif
resources = gnome.compile_resources('resources',
'../../data/zoitechat.gresource.xml',
source_dir: '../../data', # TODO: Fix upstream
source_dir: '../../data',
c_name: 'zoitechat',
extra_args: ['--manual-register']
)

View File

@@ -66,7 +66,6 @@ extern "C"
node_list->GetAt (1)->AppendChild (
toastTemplate->CreateTextNode (Platform::StringReference (wtext.c_str (), wtext.size ())));
// Mute sound, we already play our own
auto node = toastTemplate->SelectSingleNode (L"/toast");
auto audio_elem = toastTemplate->CreateElement (L"audio");
audio_elem->SetAttribute (L"silent", L"true");

View File

@@ -373,6 +373,9 @@ fe_notify_ask (char *nick, char *networks)
LABEL_NOTIFY_CANCEL, GTK_RESPONSE_REJECT,
LABEL_NOTIFY_OK, GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
if (parent_window)
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);

View File

@@ -224,6 +224,27 @@ palette_dark_set_color (int idx, const PaletteColor *col)
dark_user_colors[idx] = *col;
}
const PaletteColor *
palette_user_colors (void)
{
if (!user_colors_valid)
{
memcpy (user_colors, colors, sizeof (user_colors));
user_colors_valid = TRUE;
}
return user_colors;
}
const PaletteColor *
palette_dark_colors (void)
{
if (!dark_user_colors_valid)
return dark_colors;
return dark_user_colors;
}
void
palette_alloc (GtkWidget * widget)
{

View File

@@ -57,6 +57,8 @@ void palette_save (void);
/* Keep a copy of the user's palette so dark mode can be toggled without losing it. */
void palette_user_set_color (int idx, const PaletteColor *col);
void palette_dark_set_color (int idx, const PaletteColor *col);
const PaletteColor *palette_user_colors (void);
const PaletteColor *palette_dark_colors (void);
/*
* Apply ZoiteChat's built-in "dark mode" palette.

View File

@@ -168,7 +168,6 @@ load_pixmap (const char *filename)
g_free (path);
}
// Hack to avoid unbearably tiny icons on HiDPI screens.
scale = g_getenv ("GDK_SCALE");
if (scale)
{

View File

@@ -80,7 +80,6 @@ show_notification (const char *title, const char *text)
{
char *stripped_title, *stripped_text;
/* Strip all colors */
stripped_title = zoitechat_strip (ph, title, -1, 7);
stripped_text = zoitechat_strip (ph, text, -1, 7);
@@ -125,13 +124,10 @@ incoming_message_cb (char *word[], gpointer userdata)
flags = zoitechat_list_int(ph, NULL, "flags");
/* Let sure that can alert */
if (should_alert()) {
/* Follow the channel rules if set */
if (!(flags & CHANNEL_FLAG_BALLOON_UNSET)) {
alert = (flags & CHANNEL_FLAG_BALLOON);
} else {
/* Else follow global environment */
alert = (zoitechat_get_prefs(ph, "input_balloon_chans", NULL, &message) == 3 && message);
}
}
@@ -151,13 +147,10 @@ incoming_priv_cb (char *word[], gpointer userdata)
flags = zoitechat_list_int(ph, NULL, "flags");
/* Let sure that can alert */
if (should_alert()) {
/* Follow the private rules if set */
if (!(flags & CHANNEL_FLAG_BALLOON_UNSET)) {
alert = (flags & CHANNEL_FLAG_BALLOON);
} else {
/* Else follow global environment */
alert = (zoitechat_get_prefs(ph, "input_balloon_priv", NULL, &priv) == 3 && priv);
}
}
@@ -234,7 +227,6 @@ notification_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name, c
zoitechat_hook_print (ph, "Private Action", ZOITECHAT_PRI_LOWEST, incoming_priv_cb, NULL);
zoitechat_hook_print (ph, "Private Action to Dialog", ZOITECHAT_PRI_LOWEST, incoming_priv_cb, NULL);
/* Special events treated as priv */
zoitechat_hook_print (ph, "Notice", ZOITECHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (1));
zoitechat_hook_print (ph, "Invited", ZOITECHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (2));
zoitechat_hook_print (ph, "DCC Offer", ZOITECHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (3));

View File

@@ -781,12 +781,15 @@ servlist_deletenet_cb (GtkWidget *item, ircnet *net)
if (!net)
return;
dialog = gtk_message_dialog_new (GTK_WINDOW (serverlist_win),
GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_OK_CANCEL,
_("Really remove network \"%s\" and all its servers?"),
net->name);
GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_OK_CANCEL,
_("Really remove network \"%s\" and all its servers?"),
net->name);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
g_signal_connect (dialog, "response",
G_CALLBACK (servlist_deletenetdialog_cb), net);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
@@ -1799,6 +1802,9 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
gtk_window_set_modal (GTK_WINDOW (editwindow), TRUE);
gtk_window_set_type_hint (GTK_WINDOW (editwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
gtk_window_set_role (GTK_WINDOW (editwindow), "editserv");
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (editwindow);
vbox5 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
gtk_container_add (GTK_CONTAINER (editwindow), vbox5);
@@ -2078,6 +2084,9 @@ servlist_open_networks (void)
gtk_window_set_default_size (GTK_WINDOW (servlist), netlist_win_width, netlist_win_height);
gtk_window_set_role (GTK_WINDOW (servlist), "servlist");
gtk_window_set_type_hint (GTK_WINDOW (servlist), GDK_WINDOW_TYPE_HINT_DIALOG);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (servlist);
if (current_sess)
gtk_window_set_transient_for (GTK_WINDOW (servlist), GTK_WINDOW (current_sess->gui->window));

View File

@@ -56,6 +56,8 @@ static GtkWidget *setup_window = NULL;
static int last_selected_page = 0;
static int last_selected_row = 0; /* sound row */
static gboolean color_change;
static gboolean setup_color_edit_dark_palette;
static const PaletteColor *setup_color_edit_source_colors;
static struct zoitechatprefs setup_prefs;
static GSList *color_selector_widgets;
static GtkWidget *cancel_button;
@@ -64,11 +66,30 @@ void setup_apply_real (int new_pix, int do_ulist, int do_layout, int do_identd);
typedef struct
{
GtkWidget *combo;
GtkWidget *apply_button;
GtkWidget *status_label;
GtkWidget *gtk3_combo;
GtkWidget *gtk3_import_button;
GtkWidget *gtk3_apply_button;
GtkWidget *gtk3_use_system_button;
GtkWidget *gtk3_status_label;
GPtrArray *gtk3_theme_paths;
gboolean gtk3_force_reload_next_apply;
} setup_theme_ui;
static void
setup_theme_ui_free (gpointer data)
{
setup_theme_ui *ui = data;
if (!ui)
return;
if (ui->gtk3_theme_paths)
g_ptr_array_free (ui->gtk3_theme_paths, TRUE);
g_free (ui);
}
enum
{
ST_END,
@@ -314,15 +335,14 @@ static const char *const noticeposmenu[] =
static const char *const swtype[] =
{
N_("Tabs"), /* 0 tabs */
"", /* 1 reserved */
N_("Tree"), /* 2 tree */
N_("Tabs"),
"",
N_("Tree"),
NULL
};
static const setting tabs_settings[] =
{
/*{ST_HEADER, N_("Channel Switcher"),0,0,0},*/
{ST_RADIO, N_("Switcher type:"),P_OFFINTNL(hex_gui_tab_layout), 0, swtype, 0},
{ST_TOGGLE, N_("Open an extra tab for server messages"), P_OFFINTNL(hex_gui_tab_server), 0, 0, 0},
{ST_TOGGLE, N_("Open a new tab when you receive a private message"), P_OFFINTNL(hex_gui_autoopen_dialog), 0, 0, 0},
@@ -373,6 +393,13 @@ static const setting dark_mode_setting =
0
};
static const char *const color_edit_target_modes[] =
{
N_("Light"),
N_("Dark"),
NULL
};
static const char *const dccaccept[] =
{
N_("Ask for confirmation"),
@@ -954,7 +981,6 @@ setup_apply_trans (int *tag)
gtk_window_set_opacity (GTK_WINDOW (current_sess->gui->window),
(prefs.hex_gui_transparency / 255.));
/* mg_update_xtext (current_sess->gui->xtext); */
*tag = 0;
return 0;
}
@@ -1000,8 +1026,8 @@ setup_create_hscale (GtkWidget *table, int row, const setting *set)
}
static GtkWidget *proxy_user; /* username GtkEntry */
static GtkWidget *proxy_pass; /* password GtkEntry */
static GtkWidget *proxy_user;
static GtkWidget *proxy_pass;
static void
setup_menu_cb (GtkWidget *cbox, const setting *set)
@@ -1235,6 +1261,9 @@ setup_browsefont_cb (GtkWidget *button, GtkWidget *entry)
const char *font_name;
dialog = gtk_font_chooser_dialog_new (_("Select font"), GTK_WINDOW (setup_window));
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark/.zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
font_dialog = dialog; /* global var */
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
@@ -1476,6 +1505,9 @@ setup_create_page (const setting *set)
return tab;
}
static void
setup_color_button_apply (GtkWidget *button, const PaletteColor *color);
static void
setup_color_selectors_set_sensitive (gboolean sensitive)
{
@@ -1489,14 +1521,98 @@ setup_color_selectors_set_sensitive (gboolean sensitive)
}
}
static void
setup_color_update_source_palette (void)
{
setup_color_edit_source_colors = setup_color_edit_dark_palette
? palette_dark_colors ()
: palette_user_colors ();
}
static void
setup_refresh_color_selector_widgets (void)
{
GSList *l = color_selector_widgets;
while (l)
{
GtkWidget *w = (GtkWidget *) l->data;
gpointer color_index_ptr;
int color_index;
if (!GTK_IS_WIDGET (w))
{
l = l->next;
continue;
}
color_index_ptr = g_object_get_data (G_OBJECT (w), "zoitechat-color-index");
if (!color_index_ptr)
{
l = l->next;
continue;
}
color_index = GPOINTER_TO_INT (color_index_ptr);
if (setup_color_edit_source_colors && color_index >= 0 && color_index <= MAX_COL)
setup_color_button_apply (w, &setup_color_edit_source_colors[color_index]);
l = l->next;
}
}
static void
setup_dark_mode_menu_cb (GtkWidget *cbox, const setting *set)
{
setup_menu_cb (cbox, set);
setup_color_update_source_palette ();
setup_refresh_color_selector_widgets ();
/* Keep color selectors usable even when dark mode is enabled. */
setup_color_selectors_set_sensitive (TRUE);
}
static void
setup_color_edit_target_menu_cb (GtkComboBox *cbox, gpointer userdata)
{
(void) userdata;
setup_color_edit_dark_palette = gtk_combo_box_get_active (cbox) == 1;
setup_color_update_source_palette ();
setup_refresh_color_selector_widgets ();
setup_color_selectors_set_sensitive (TRUE);
}
static GtkWidget *
setup_create_color_edit_target_menu (GtkWidget *table, int row)
{
GtkWidget *wid;
GtkWidget *cbox;
GtkWidget *box;
int i;
wid = gtk_label_new (_("Editing:"));
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
cbox = gtk_combo_box_text_new ();
for (i = 0; color_edit_target_modes[i]; i++)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cbox), _(color_edit_target_modes[i]));
gtk_combo_box_set_active (GTK_COMBO_BOX (cbox), setup_color_edit_dark_palette ? 1 : 0);
g_signal_connect (G_OBJECT (cbox), "changed",
G_CALLBACK (setup_color_edit_target_menu_cb), NULL);
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), cbox, 0, 0, 0);
setup_table_attach (table, box, 3, 4, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
return cbox;
}
static GtkWidget *
setup_create_dark_mode_menu (GtkWidget *table, int row, const setting *set)
{
@@ -1545,8 +1661,7 @@ setup_color_button_apply (GtkWidget *button, const PaletteColor *color)
typedef struct
{
GtkWidget *button;
PaletteColor *color;
int color_index;
} setup_color_dialog_data;
static void
@@ -1577,14 +1692,15 @@ setup_color_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data
GdkRGBA rgba;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &rgba);
*data->color = rgba;
color_change = TRUE;
setup_color_button_apply (data->button, data->color);
if (fe_dark_mode_is_enabled_for (setup_prefs.hex_gui_dark_mode))
palette_dark_set_color ((int)(data->color - colors), data->color);
if (setup_color_edit_dark_palette)
palette_dark_set_color (data->color_index, &rgba);
else
palette_user_set_color ((int)(data->color - colors), data->color);
palette_user_set_color (data->color_index, &rgba);
color_change = TRUE;
setup_color_update_source_palette ();
setup_refresh_color_selector_widgets ();
}
gtk_widget_destroy (GTK_WIDGET (dialog));
@@ -1595,20 +1711,26 @@ static void
setup_color_cb (GtkWidget *button, gpointer userdata)
{
GtkWidget *dialog;
PaletteColor *color;
int color_index;
GdkRGBA rgba;
setup_color_dialog_data *data;
color = &colors[GPOINTER_TO_INT (userdata)];
(void) button;
color_index = GPOINTER_TO_INT (userdata);
dialog = gtk_color_chooser_dialog_new (_("Select color"), GTK_WINDOW (setup_window));
setup_rgba_from_palette (color, &rgba);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark/.zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
if (setup_color_edit_source_colors && color_index >= 0 && color_index <= MAX_COL)
setup_rgba_from_palette (&setup_color_edit_source_colors[color_index], &rgba);
else
setup_rgba_from_palette (&colors[color_index], &rgba);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (dialog), &rgba);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
data = g_new0 (setup_color_dialog_data, 1);
data->button = button;
data->color = color;
data->color_index = color_index;
g_signal_connect (dialog, "response", G_CALLBACK (setup_color_response_cb), data);
gtk_widget_show (dialog);
}
@@ -1642,11 +1764,15 @@ setup_create_color_button (GtkWidget *table, int num, int row, int col)
/* win32 build uses this to turn off themeing */
g_object_set_data (G_OBJECT (but), "zoitechat-color", (gpointer)1);
g_object_set_data (G_OBJECT (but), "zoitechat-color-box", box);
g_object_set_data (G_OBJECT (but), "zoitechat-color-index", GINT_TO_POINTER (num));
setup_table_attach (table, but, col, col + 1, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_CENTER, SETUP_ALIGN_CENTER, 0, 0);
g_signal_connect (G_OBJECT (but), "clicked",
G_CALLBACK (setup_color_cb), GINT_TO_POINTER (num));
setup_color_button_apply (but, &colors[num]);
if (setup_color_edit_source_colors)
setup_color_button_apply (but, &setup_color_edit_source_colors[num]);
else
setup_color_button_apply (but, &colors[num]);
/* Track all color selector widgets (used for dark mode UI behavior). */
color_selector_widgets = g_slist_prepend (color_selector_widgets, but);
@@ -1684,6 +1810,8 @@ static GtkWidget *
setup_create_color_page (void)
{
color_selector_widgets = NULL;
setup_color_edit_dark_palette = setup_prefs.hex_gui_dark_mode == ZOITECHAT_DARK_MODE_DARK;
setup_color_update_source_palette ();
GtkWidget *tab, *box, *label;
int i;
@@ -1736,8 +1864,10 @@ setup_create_color_page (void)
setup_create_other_color (_("Highlight:"), COL_HILIGHT, 11, tab);
setup_create_other_colorR (_("Spell checker:"), COL_SPELL, 11, tab);
setup_create_dark_mode_menu (tab, 13, &dark_mode_setting);
setup_create_color_edit_target_menu (tab, 14);
setup_refresh_color_selector_widgets ();
setup_color_selectors_set_sensitive (TRUE);
setup_create_header (tab, 15, N_("Color Stripping"));
setup_create_header (tab, 16, N_("Color Stripping"));
/* label = gtk_label_new (_("Strip colors from:"));
gtk_widget_set_halign (label, GTK_ALIGN_START);
@@ -1748,7 +1878,7 @@ setup_create_color_page (void)
for (i = 0; i < 3; i++)
{
setup_create_toggleL (tab, i + 16, &color_settings[i]);
setup_create_toggleL (tab, i + 17, &color_settings[i]);
}
return box;
@@ -1761,121 +1891,230 @@ setup_theme_show_message (GtkMessageType message_type, const char *primary)
dialog = gtk_message_dialog_new (GTK_WINDOW (setup_window), GTK_DIALOG_MODAL,
message_type, GTK_BUTTONS_CLOSE, "%s", primary);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
static void
setup_theme_populate (setup_theme_ui *ui)
setup_gtk3_theme_populate (setup_theme_ui *ui)
{
char *themes_dir;
GDir *dir;
const char *name;
GtkTreeModel *model;
GtkTreeIter iter;
int count;
char *themes_dir;
GtkTreeModel *model;
GtkTreeIter iter;
GDir *dir;
const char *name;
gboolean have_valid_theme = FALSE;
gint active = -1;
guint i;
model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->combo));
while (gtk_tree_model_get_iter_first (model, &iter))
gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (ui->combo), 0);
themes_dir = g_build_filename (get_xdir (), "gtk3-themes", NULL);
g_mkdir_with_parents (themes_dir, 0700);
themes_dir = g_build_filename (get_xdir (), "themes", NULL);
if (!g_file_test (themes_dir, G_FILE_TEST_IS_DIR))
g_mkdir_with_parents (themes_dir, 0700);
model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->gtk3_combo));
while (gtk_tree_model_get_iter_first (model, &iter))
gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (ui->gtk3_combo), 0);
dir = g_dir_open (themes_dir, 0, NULL);
if (dir)
{
while ((name = g_dir_read_name (dir)))
{
char *path = g_build_filename (themes_dir, name, NULL);
if (g_file_test (path, G_FILE_TEST_IS_DIR))
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (ui->combo), name);
g_free (path);
}
g_dir_close (dir);
}
if (!ui->gtk3_theme_paths)
ui->gtk3_theme_paths = g_ptr_array_new_with_free_func (g_free);
else
g_ptr_array_set_size (ui->gtk3_theme_paths, 0);
count = gtk_tree_model_iter_n_children (gtk_combo_box_get_model (GTK_COMBO_BOX (ui->combo)), NULL);
if (count > 0)
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->combo), 0);
dir = g_dir_open (themes_dir, 0, NULL);
if (dir)
{
while ((name = g_dir_read_name (dir)))
{
char *theme_path;
char *gtk3_dir = NULL;
gtk_widget_set_sensitive (ui->apply_button, count > 0);
gtk_label_set_text (GTK_LABEL (ui->status_label),
count > 0 ? _("Select a theme to apply.") : _("No themes found."));
theme_path = g_build_filename (themes_dir, name, NULL);
g_free (themes_dir);
if (g_file_test (theme_path, G_FILE_TEST_IS_DIR)
&& fe_resolve_gtk3_theme_dir (theme_path, &gtk3_dir, NULL))
{
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (ui->gtk3_combo), name);
g_ptr_array_add (ui->gtk3_theme_paths, theme_path);
have_valid_theme = TRUE;
theme_path = NULL;
}
g_free (gtk3_dir);
g_free (theme_path);
}
g_dir_close (dir);
}
if (!have_valid_theme)
{
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("No valid GTK3 themes found."));
}
else
{
for (i = 0; i < ui->gtk3_theme_paths->len; i++)
{
const char *theme_path = g_ptr_array_index (ui->gtk3_theme_paths, i);
char *theme_name = g_path_get_basename (theme_path);
if (g_strcmp0 (prefs.hex_gui_gtk3_theme_name, theme_name) == 0)
{
active = (gint) i;
g_free (theme_name);
break;
}
g_free (theme_name);
}
if (active >= 0)
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->gtk3_combo), active);
else if (prefs.hex_gui_gtk3_theme_name[0] == '\0')
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->gtk3_combo), 0);
else
gtk_combo_box_set_active (GTK_COMBO_BOX (ui->gtk3_combo), -1);
if (gtk_combo_box_get_active (GTK_COMBO_BOX (ui->gtk3_combo)) >= 0)
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("Select a GTK3 theme to apply."));
else
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("No valid GTK3 themes found."));
}
gtk_widget_set_sensitive (ui->gtk3_apply_button,
gtk_combo_box_get_active (GTK_COMBO_BOX (ui->gtk3_combo)) >= 0);
g_free (themes_dir);
}
static void
setup_theme_refresh_cb (GtkWidget *button, gpointer user_data)
setup_theme_gtk3_selection_changed (GtkComboBox *combo, gpointer user_data)
{
setup_theme_ui *ui = user_data;
setup_theme_ui *ui = user_data;
gboolean has_selection = gtk_combo_box_get_active (combo) >= 0;
setup_theme_populate (ui);
gtk_widget_set_sensitive (ui->gtk3_apply_button, has_selection);
}
static void
setup_theme_open_folder_cb (GtkWidget *button, gpointer user_data)
setup_theme_gtk3_import_cb (GtkWidget *button, gpointer user_data)
{
char *themes_dir;
setup_theme_ui *ui = user_data;
GtkWidget *dialog;
GtkFileFilter *filter;
gint response;
char *archive_path;
GError *error = NULL;
themes_dir = g_build_filename (get_xdir (), "themes", NULL);
g_mkdir_with_parents (themes_dir, 0700);
fe_open_url (themes_dir);
g_free (themes_dir);
dialog = gtk_file_chooser_dialog_new (_("Import GTK3 Theme Archive"), GTK_WINDOW (setup_window),
GTK_FILE_CHOOSER_ACTION_OPEN,
_ ("_Cancel"), GTK_RESPONSE_CANCEL,
_ ("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
/* Window classes are required for GTK CSS selectors like
* .zoitechat-dark / .zoitechat-light. */
fe_apply_theme_to_toplevel (dialog);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Theme archives (.zip, .tar.xz, .tar.gz, .tar)"));
gtk_file_filter_add_pattern (filter, "*.zip");
gtk_file_filter_add_pattern (filter, "*.ZIP");
gtk_file_filter_add_pattern (filter, "*.tar");
gtk_file_filter_add_pattern (filter, "*.tar.gz");
gtk_file_filter_add_pattern (filter, "*.tgz");
gtk_file_filter_add_pattern (filter, "*.tar.xz");
gtk_file_filter_add_pattern (filter, "*.txz");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response != GTK_RESPONSE_ACCEPT)
{
gtk_widget_destroy (dialog);
return;
}
archive_path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
gtk_widget_destroy (dialog);
if (!archive_path)
return;
if (!zoitechat_import_gtk3_theme_archive (archive_path, NULL, &error))
{
setup_theme_show_message (GTK_MESSAGE_ERROR,
error ? error->message : _("Failed to import GTK3 theme archive."));
g_clear_error (&error);
}
else
{
ui->gtk3_force_reload_next_apply = TRUE;
setup_gtk3_theme_populate (ui);
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("GTK3 theme archive imported successfully."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("GTK3 theme archive imported successfully."));
}
g_free (archive_path);
}
static void
setup_theme_apply_gtk3_cb (GtkWidget *button, gpointer user_data)
{
setup_theme_ui *ui = user_data;
gint active;
const char *theme_path;
char *theme;
GError *error = NULL;
active = gtk_combo_box_get_active (GTK_COMBO_BOX (ui->gtk3_combo));
if (active < 0 || !ui->gtk3_theme_paths || (guint) active >= ui->gtk3_theme_paths->len)
return;
theme_path = g_ptr_array_index (ui->gtk3_theme_paths, active);
theme = g_path_get_basename (theme_path);
if (!theme || !*theme)
{
g_free (theme);
return;
}
if (!fe_apply_gtk3_theme_with_reload (theme, ui->gtk3_force_reload_next_apply, &error))
{
setup_theme_show_message (GTK_MESSAGE_ERROR,
error ? error->message : _("Failed to apply GTK3 theme."));
g_clear_error (&error);
g_free (theme);
return;
}
ui->gtk3_force_reload_next_apply = FALSE;
safe_strcpy (prefs.hex_gui_gtk3_theme_name, theme, sizeof (prefs.hex_gui_gtk3_theme_name));
/* Keep the Preferences working copy in sync so pressing OK does not
* overwrite the just-selected theme with stale setup_prefs data. */
safe_strcpy (setup_prefs.hex_gui_gtk3_theme_name, theme,
sizeof (setup_prefs.hex_gui_gtk3_theme_name));
save_config ();
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("GTK3 theme activated from ZoiteChat's local theme store."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("GTK3 theme activated and saved."));
g_free (theme);
}
static void
setup_theme_selection_changed (GtkComboBox *combo, gpointer user_data)
setup_theme_gtk3_use_system_cb (GtkWidget *button, gpointer user_data)
{
setup_theme_ui *ui = user_data;
gboolean has_selection = gtk_combo_box_get_active (combo) >= 0;
setup_theme_ui *ui = user_data;
gtk_widget_set_sensitive (ui->apply_button, has_selection);
}
static void
setup_theme_apply_cb (GtkWidget *button, gpointer user_data)
{
setup_theme_ui *ui = user_data;
GtkWidget *dialog;
gint response;
char *theme;
GError *error = NULL;
theme = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (ui->combo));
if (!theme)
return;
dialog = gtk_message_dialog_new (GTK_WINDOW (setup_window), GTK_DIALOG_MODAL,
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
"%s", _("Applying a theme will overwrite your current colors and event settings.\nContinue?"));
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
if (response != GTK_RESPONSE_OK)
{
g_free (theme);
return;
}
if (!zoitechat_apply_theme (theme, &error))
{
setup_theme_show_message (GTK_MESSAGE_ERROR, error ? error->message : _("Failed to apply theme."));
g_clear_error (&error);
goto cleanup;
}
palette_load ();
palette_apply_dark_mode (fe_dark_mode_is_enabled ());
color_change = TRUE;
setup_apply_real (0, TRUE, FALSE, FALSE);
setup_theme_show_message (GTK_MESSAGE_INFO, _("Theme applied. Some changes may require a restart to take full effect."));
cleanup:
g_free (theme);
fe_apply_gtk3_theme (NULL, NULL);
ui->gtk3_force_reload_next_apply = FALSE;
prefs.hex_gui_gtk3_theme_name[0] = '\0';
setup_prefs.hex_gui_gtk3_theme_name[0] = '\0';
save_config ();
gtk_label_set_text (GTK_LABEL (ui->gtk3_status_label), _("Using system GTK theme."));
setup_theme_show_message (GTK_MESSAGE_INFO, _("Using system GTK theme."));
}
static GtkWidget *
@@ -1883,62 +2122,59 @@ setup_create_theme_page (void)
{
setup_theme_ui *ui;
GtkWidget *box;
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *button_box;
char *themes_dir;
char *markup;
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *button_box;
GtkWidget *frame;
ui = g_new0 (setup_theme_ui, 1);
box = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (box), 6);
themes_dir = g_build_filename (get_xdir (), "themes", NULL);
markup = g_markup_printf_escaped (_("Theme files are loaded from <tt>%s</tt>."), themes_dir);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
g_free (markup);
g_free (themes_dir);
frame = gtk_frame_new (_("GTK3 Theme"));
gtk_box_pack_start (GTK_BOX (box), frame, FALSE, FALSE, 0);
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0);
hbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
gtk_container_add (GTK_CONTAINER (frame), hbox);
ui->combo = gtk_combo_box_text_new ();
gtk_box_pack_start (GTK_BOX (hbox), ui->combo, TRUE, TRUE, 0);
g_signal_connect (G_OBJECT (ui->combo), "changed",
G_CALLBACK (setup_theme_selection_changed), ui);
label = gtk_label_new (_("Import a GTK3 theme archive or select a GTK3 theme installed in ZoiteChat's local theme store."));
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
button_box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, FALSE, 0);
button_box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, FALSE, 0);
ui->apply_button = gtk_button_new_with_mnemonic (_("_Apply Theme"));
gtk_box_pack_start (GTK_BOX (button_box), ui->apply_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (ui->apply_button), "clicked",
G_CALLBACK (setup_theme_apply_cb), ui);
ui->gtk3_combo = gtk_combo_box_text_new ();
gtk_box_pack_start (GTK_BOX (button_box), ui->gtk3_combo, TRUE, TRUE, 0);
g_signal_connect (G_OBJECT (ui->gtk3_combo), "changed",
G_CALLBACK (setup_theme_gtk3_selection_changed), ui);
label = gtk_button_new_with_mnemonic (_("_Refresh"));
gtk_box_pack_start (GTK_BOX (button_box), label, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (label), "clicked",
G_CALLBACK (setup_theme_refresh_cb), ui);
ui->gtk3_import_button = gtk_button_new_with_mnemonic (_("_Import GTK3 Theme Archive"));
gtk_box_pack_start (GTK_BOX (button_box), ui->gtk3_import_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (ui->gtk3_import_button), "clicked",
G_CALLBACK (setup_theme_gtk3_import_cb), ui);
label = gtk_button_new_with_mnemonic (_("_Open Folder"));
gtk_box_pack_start (GTK_BOX (button_box), label, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (label), "clicked",
G_CALLBACK (setup_theme_open_folder_cb), ui);
ui->gtk3_apply_button = gtk_button_new_with_mnemonic (_("Apply GTK_3 Theme"));
gtk_box_pack_start (GTK_BOX (button_box), ui->gtk3_apply_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (ui->gtk3_apply_button), "clicked",
G_CALLBACK (setup_theme_apply_gtk3_cb), ui);
ui->status_label = gtk_label_new (NULL);
gtk_widget_set_halign (ui->status_label, GTK_ALIGN_START);
gtk_widget_set_valign (ui->status_label, GTK_ALIGN_CENTER);
gtk_box_pack_start (GTK_BOX (box), ui->status_label, FALSE, FALSE, 0);
ui->gtk3_use_system_button = gtk_button_new_with_mnemonic (_("Use _System GTK Theme"));
gtk_box_pack_start (GTK_BOX (button_box), ui->gtk3_use_system_button, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (ui->gtk3_use_system_button), "clicked",
G_CALLBACK (setup_theme_gtk3_use_system_cb), ui);
setup_theme_populate (ui);
ui->gtk3_status_label = gtk_label_new (NULL);
gtk_widget_set_halign (ui->gtk3_status_label, GTK_ALIGN_START);
gtk_widget_set_valign (ui->gtk3_status_label, GTK_ALIGN_CENTER);
gtk_box_pack_start (GTK_BOX (hbox), ui->gtk3_status_label, FALSE, FALSE, 0);
g_object_set_data_full (G_OBJECT (box), "setup-theme-ui", ui, g_free);
setup_gtk3_theme_populate (ui);
g_object_set_data_full (G_OBJECT (box), "setup-theme-ui", ui, setup_theme_ui_free);
return box;
}
@@ -2414,6 +2650,47 @@ setup_apply_entry_style (GtkWidget *entry)
input_style->font_desc);
}
static void
setup_apply_input_caret_provider (GtkWidget *widget, const char *css)
{
GtkCssProvider *provider;
GtkStyleContext *context;
if (!widget)
return;
context = gtk_widget_get_style_context (widget);
provider = g_object_get_data (G_OBJECT (widget), "zoitechat-input-caret-provider");
if (!provider)
{
provider = gtk_css_provider_new ();
g_object_set_data_full (G_OBJECT (widget), "zoitechat-input-caret-provider",
provider, g_object_unref);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
gtk_css_provider_load_from_data (provider, css, -1, NULL);
}
static void
setup_remove_input_caret_provider (GtkWidget *widget)
{
GtkCssProvider *provider;
GtkStyleContext *context;
if (!widget)
return;
context = gtk_widget_get_style_context (widget);
provider = g_object_get_data (G_OBJECT (widget), "zoitechat-input-caret-provider");
if (!provider)
return;
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
g_object_set_data (G_OBJECT (widget), "zoitechat-input-caret-provider", NULL);
}
static void
setup_apply_to_sess (session_gui *gui)
{
@@ -2439,35 +2716,29 @@ setup_apply_to_sess (session_gui *gui)
if (prefs.hex_gui_input_style)
{
char buf[128];
GtkCssProvider *provider = gtk_css_provider_new ();
GtkStyleContext *context;
char *color_string = gdk_rgba_to_string (&colors[COL_FG]);
g_snprintf (buf, sizeof (buf), ".zoitechat-inputbox { caret-color: %s; }",
g_snprintf (buf, sizeof (buf), "#zoitechat-inputbox { caret-color: %s; }",
color_string);
gtk_css_provider_load_from_data (provider, buf, -1, NULL);
g_free (color_string);
context = gtk_widget_get_style_context (gui->input_box);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
context = gtk_widget_get_style_context (gui->limit_entry);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
context = gtk_widget_get_style_context (gui->key_entry);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
context = gtk_widget_get_style_context (gui->topic_entry);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
setup_apply_input_caret_provider (gui->input_box, buf);
setup_apply_input_caret_provider (gui->limit_entry, buf);
setup_apply_input_caret_provider (gui->key_entry, buf);
setup_apply_input_caret_provider (gui->topic_entry, buf);
setup_apply_entry_style (gui->input_box);
setup_apply_entry_style (gui->limit_entry);
setup_apply_entry_style (gui->key_entry);
setup_apply_entry_style (gui->topic_entry);
}
else
{
setup_remove_input_caret_provider (gui->input_box);
setup_remove_input_caret_provider (gui->limit_entry);
setup_remove_input_caret_provider (gui->key_entry);
setup_remove_input_caret_provider (gui->topic_entry);
}
if (prefs.hex_gui_ulist_buttons)
gtk_widget_show (gui->button_box);
@@ -2744,6 +3015,7 @@ setup_window_open (void)
gtk_box_pack_start (GTK_BOX (hbbox), wid, FALSE, FALSE, 0);
gtk_widget_show_all (win);
fe_apply_theme_to_toplevel (win);
return win;
}
@@ -2759,6 +3031,8 @@ setup_close_cb (GtkWidget *win, GtkWidget **swin)
color_selector_widgets = NULL;
}
setup_color_edit_source_colors = NULL;
if (font_dialog)
{
gtk_widget_destroy (font_dialog);

View File

@@ -37,7 +37,6 @@
#define ICON_URLGRAB_COPY "zc-menu-copy"
#define ICON_URLGRAB_SAVE_AS "zc-menu-save-as"
/* model for the URL treeview */
enum
{
URL_COLUMN,
@@ -60,7 +59,6 @@ url_treeview_url_clicked_cb (GtkWidget *view, GdkEventButton *event,
if (!event || !gtk_tree_view_get_path_at_pos (tree, event->x, event->y, &path, 0, 0, 0))
return FALSE;
/* select what they right-clicked on */
sel = gtk_tree_view_get_selection (tree);
gtk_tree_selection_unselect_all (sel);
gtk_tree_selection_select_path (sel, path);
@@ -103,7 +101,6 @@ url_treeview_new (GtkWidget *box)
gtk_widget_set_vexpand (scroll, TRUE);
g_signal_connect (G_OBJECT (view), "button_press_event",
G_CALLBACK (url_treeview_url_clicked_cb), NULL);
/* don't want column headers */
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
gtk_widget_show (view);
return view;
@@ -172,7 +169,6 @@ fe_url_add (const char *urltext)
URL_COLUMN, urltext,
-1);
/* remove any overflow */
if (prefs.hex_url_grabber_limit > 0)
{
valid = gtk_tree_model_iter_nth_child (

View File

@@ -44,7 +44,7 @@
#include "fe-text.h"
static int done = FALSE; /* finished ? */
static int done = FALSE;
static void
@@ -227,10 +227,9 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
i++;
}
break;
/* don't actually want hidden text */
case '\010': /* hidden */
case '\010':
break;
case '\026': /* REVERSE */
case '\026':
if (reverse)
{
reverse = FALSE;
@@ -242,7 +241,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
}
j = strlen (newtext);
break;
case '\037': /* underline */
case '\037':
if (under)
{
under = FALSE;
@@ -254,7 +253,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
}
j = strlen (newtext);
break;
case '\002': /* bold */
case '\002':
if (bold)
{
bold = FALSE;
@@ -273,7 +272,7 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
j++;
}
break;
case '\017': /* reset all */
case '\017':
strcpy (&newtext[j], "\033[m");
j += 3;
reverse = FALSE;
@@ -361,12 +360,11 @@ fe_print_text (struct session *sess, char *text, time_t stamp,
i++;
}
break;
/* don't actually want hidden text */
case '\010': /* hidden */
case '\026': /* REVERSE */
case '\037': /* underline */
case '\002': /* bold */
case '\017': /* reset all */
case '\010':
case '\026':
case '\037':
case '\002':
case '\017':
break;
case '\007':
if (!prefs.hex_input_filter_beep)
@@ -535,7 +533,7 @@ fe_args (int argc, char *argv[])
return 0;
}
if (arg_cfgdir) /* we want filesystem encoding */
if (arg_cfgdir)
{
g_free (xdir);
xdir = g_strdup(arg_cfgdir);
@@ -550,10 +548,8 @@ fe_args (int argc, char *argv[])
void
fe_init (void)
{
/* the following should be default generated, not enfoced in binary */
prefs.hex_gui_tab_server = 0;
prefs.hex_gui_autoopen_dialog = 0;
/* except for these, there is no lag meter, there is no server list */
prefs.hex_gui_lagometer = 0;
prefs.hex_gui_slist_skip = 1;
}
@@ -565,7 +561,6 @@ fe_main (void)
main_loop = g_main_loop_new(NULL, FALSE);
/* Keyboard Entry Setup */
#ifdef G_OS_WIN32
keyboard_input = g_io_channel_win32_new_fd(STDIN_FILENO);
#else
@@ -834,10 +829,8 @@ fe_idle_add (void *func, void *data)
void
fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
{
/* only one action type handled for now, but could add more */
switch (action)
{
/* gui focus is really the only case zoitechat-text needs to worry about */
case FE_GUI_FOCUS:
current_sess = sess;
current_tab = sess;

View File

@@ -32,8 +32,6 @@
ENCHANT_PLUGIN_DECLARE ("win8")
/* --------- Utils ----------*/
static char *
utf16_to_utf8 (const wchar_t * const str, bool from_bcp47)
{
@@ -106,7 +104,7 @@ utf8_to_utf16 (const char * const str, int len, bool to_bcp47)
static char **
enumstring_to_chararray (IEnumString *strings, size_t *out_len, bool from_bcp47)
{
char **chars = static_cast<char**>(std::calloc (256, sizeof (char*))); /* Hopefully large enough */
char **chars = static_cast<char**>(std::calloc (256, sizeof (char*)));
LPOLESTR wstr = nullptr;
size_t i = 0;
@@ -134,8 +132,6 @@ enumstring_to_chararray (IEnumString *strings, size_t *out_len, bool from_bcp47)
return chars;
}
/* ---------- Dict ------------ */
static void
win8_dict_add_to_personal (EnchantDict *dict, const char *const word, size_t len)
{
@@ -169,18 +165,18 @@ win8_dict_check (EnchantDict *dict, const char *const word, size_t len)
std::free (wword);
if (FAILED (hr))
return -1; /* Error */
return -1;
if (errors->Next (&error) == S_OK)
{
error->Release ();
errors->Release ();
return 1; /* Spelling Issue */
return 1;
}
else
{
errors->Release ();
return 0; /* Correct */
return 0;
}
}
@@ -204,8 +200,6 @@ win8_dict_suggest (EnchantDict *dict, const char *const word, size_t len, size_t
return enumstring_to_chararray (suggestions, out_n_suggs, false);
}
/* ---------- Provider ------------ */
static EnchantDict *
win8_provider_request_dict (EnchantProvider *provider, const char *const tag)
{
@@ -225,7 +219,7 @@ win8_provider_request_dict (EnchantProvider *provider, const char *const tag)
dict->suggest = win8_dict_suggest;
dict->check = win8_dict_check;
dict->add_to_personal = win8_dict_add_to_personal;
dict->add_to_exclude = win8_dict_add_to_personal; /* Basically the same */
dict->add_to_exclude = win8_dict_add_to_personal;
dict->add_to_session = win8_dict_add_to_session;
dict->user_data = checker;

View File

@@ -27,6 +27,8 @@ DefaultDirName={pf64}\ZoiteChat
#else
DefaultDirName={pf32}\ZoiteChat
#endif
DisableDirPage=no
UsePreviousAppDir=no
DefaultGroupName=ZoiteChat
AllowNoIcons=yes
SolidCompression=yes