/* GTK+ Preference Tool
* Copyright (C) 2003-2005 Alex Shaduri.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/***************************************************************************
win32util.cpp - description
-------------------
begin : Tue Jan 14 2003
copyright : (C) 2003 by Alex Shaduri
email : alex_sh@land.ru
***************************************************************************/
#ifdef _WIN32
#include <string>
#include "sys_win32.h"
#include "win32util.h"
std::string win32_get_registry_value_string(HKEY base, const std::string& keydir, const std::string& key)
{
HKEY reg_key = NULL;
DWORD type;
DWORD nbytes;
char* result = NULL;
//HKEY_CURRENT_USER
nbytes = 0;
if ( RegOpenKeyEx ( base, keydir.c_str(), 0, KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS
&& RegQueryValueEx (reg_key, key.c_str(), 0, &type, NULL, &nbytes) == ERROR_SUCCESS ) {
resultpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//* per-channel/dialog settings :: /CHANOPT */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "xchat.h"
#include "cfgfiles.h"
#include "server.h"
#include "text.h"
#include "util.h"
#include "xchatc.h"
static GSList *chanopt_list = NULL;
static gboolean chanopt_open = FALSE;
static gboolean chanopt_changed = FALSE;
typedef struct
{
char *name;
char *alias; /* old names from 2.8.4 */
int offset;
} channel_options;
#define S_F(xx) STRUCT_OFFSET_STR(struct session,xx)
static const channel_options chanopt[] =
{
{"alert_beep", "BEEP", S_F(alert_beep)},
{"alert_taskbar", NULL, S_F(alert_taskbar)},
{"alert_tray", "TRAY", S_F(alert_tray)},
{"text_hidejoinpart", "CONFMODE", S_F(text_hidejoinpart)},
{"text_logging", NULL, S_F(text_logging)},
{"text_scrollback", NULL, S_F(text_scrollback)},
};
#undef S_F
static char *
chanopt_value (guint8 val)
{
switch (val)
{
case SET_OFF:
return "OFF";
case SET_ON:
return "ON";
default:
return "{unset}";
}
}
/* handle the /CHANOPT command */
int
chanopt_command (session *sess, char *tbuf, char *word[], char *word_eol[])
{
int dots, i = 0, j, p = 0;
guint8 val;
int offset = 2;
char *find;
gboolean quiet = FALSE;
int newval = -1;
if (!strcmp (word[2], "-quiet"))
{
quiet = TRUE;
offset++;
}
find = word[offset++];
if (word[offset][0])
{
if (!strcasecmp (word[offset], "ON"))
newval = 1;
else if (!strcasecmp (word[offset], "OFF"))
newval = 0;
else if (word[offset][0] == 'u')
newval = SET_DEFAULT;
else
newval = atoi (word[offset]);
}
if (!quiet)
PrintTextf (sess, "\002Network\002: %s \002Channel\002: %s\n",
sess->server->network ? server_get_network (sess->server, TRUE) : _("<none>"),
sess->channel[0] ? sess->channel : _("<none>"));
while (i < sizeof (chanopt) / sizeof (channel_options))
{
if (find[0] == 0 || match (find, chanopt[i].name) || (chanopt[i].alias && match (find, chanopt[i].alias)))
{
if (newval != -1) /* set new value */
{
*(guint8 *)G_STRUCT_MEMBER_P(sess, chanopt[i].offset) = newval;
}
if (!quiet) /* print value */
{
strcpy (tbuf, chanopt[i].name);
p = strlen (tbuf);
tbuf[p++] = 3;
tbuf[p++] = '2';
dots = 20 - strlen (chanopt[i].name);
for (j = 0; j < dots; j++)
tbuf[p++] = '.';
tbuf[p++] = 0;
val = G_STRUCT_MEMBER (guint8, sess, chanopt[i].offset);
PrintTextf (sess, "%s\0033:\017 %s", tbuf, chanopt_value (val));
}
}
i++;
}
return TRUE;
}
/* is a per-channel setting set? Or is it UNSET and
* the global version is set? */
gboolean
chanopt_is_set (unsigned int global, guint8 per_chan_setting)
{
if (per_chan_setting == SET_DEFAULT)
return global;
return per_chan_setting;
}
/* additive version */
gboolean
chanopt_is_set_a (unsigned int global, guint8 per_chan_setting)
{
if (per_chan_setting == SET_DEFAULT)
return global;
return per_chan_setting || 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_beep;
guint8 alert_taskbar;
guint8 alert_tray;
/* Per-Channel Settings */
guint8 text_hidejoinpart;
guint8 text_logging;
guint8 text_scrollback;
char *network;
char *channel;
} chanopt_in_memory;
static chanopt_in_memory *
chanopt_find (char *network, char *channel, gboolean add_new)
{
GSList *list;
chanopt_in_memory *co;
int i;
for (list = chanopt_list; list; list = list->next)
{
co = list->data;
if (!strcasecmp (co->channel, channel) &&
!strcasecmp (co->network, network))
return co;
}
if (!add_new)
return NULL;
/* allocate a new one */
co = g_malloc0 (sizeof (chanopt_in_memory));
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))
{
*(guint8 *)G_STRUCT_MEMBER_P(co, chanopt[i].offset) = SET_DEFAULT;
i++;
}
chanopt_list = g_slist_prepend (chanopt_list, co);
chanopt_changed = TRUE;
return co;
}
static void
chanopt_add_opt (chanopt_in_memory *co, char *var, int new_value)
{
int i;
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
if (!strcmp (var, chanopt[i].name))
{
*(guint8 *)G_STRUCT_MEMBER_P(co, chanopt[i].offset) = new_value;
}
i++;
}
}
/* load chanopt.conf from disk into our chanopt_list GSList */
static void
chanopt_load_all (void)
{
int fh;
char buf[256];
char *eq;
char *network = NULL;
chanopt_in_memory *current = NULL;
/* 1. load the old file into our GSList */
fh = xchat_open_file ("chanopt.conf", O_RDONLY, 0, 0);
if (fh != -1)
{
while (waitline (fh, buf, sizeof buf, FALSE) != -1)
{
eq = strchr (buf, '=');
if (!eq)
continue;
eq[0] = 0;
if (eq != buf && eq[-1] == ' ')
eq[-1] = 0;
if (!strcmp (buf, "network"))
{
g_free (network);
network = g_strdup (eq + 2);
}
else if (!strcmp (buf, "channel"))
{
current = chanopt_find (network, eq + 2, TRUE);
chanopt_changed = FALSE;
}
else
{
if (current)
chanopt_add_opt (current, buf, atoi (eq + 2));
}
}
close (fh);
g_free (network);
}
}
void
chanopt_load (session *sess)
{
int i;
guint8 val;
chanopt_in_memory *co;
char *network;
if (sess->channel[0] == 0)
return;
network = server_get_network (sess->server, FALSE);
if (!network)
return;
if (!chanopt_open)
{
chanopt_open = TRUE;
chanopt_load_all ();
}
co = chanopt_find (network, sess->channel, FALSE);
if (!co)
return;
/* fill in all the sess->xxxxx fields */
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
val = G_STRUCT_MEMBER(guint8, co, chanopt[i].offset);
*(guint8 *)G_STRUCT_MEMBER_P(sess, chanopt[i].offset) = val;
i++;
}
}
void
chanopt_save (session *sess)
{
int i;
guint8 vals;
guint8 valm;
chanopt_in_memory *co;
char *network;
if (sess->channel[0] == 0)
return;
network = server_get_network (sess->server, FALSE);
if (!network)
return;
/* 2. reconcile sess with what we loaded from disk */
co = chanopt_find (network, sess->channel, TRUE);
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
vals = G_STRUCT_MEMBER(guint8, sess, chanopt[i].offset);
valm = G_STRUCT_MEMBER(guint8, co, chanopt[i].offset);
if (vals != valm)
{
*(guint8 *)G_STRUCT_MEMBER_P(co, chanopt[i].offset) = vals;
chanopt_changed = TRUE;
}
i++;
}
}
static void
chanopt_save_one_channel (chanopt_in_memory *co, int fh)
{
int i;
char buf[256];
guint8 val;
snprintf (buf, sizeof (buf), "%s = %s\n", "network", co->network);
write (fh, buf, strlen (buf));
snprintf (buf, sizeof (buf), "%s = %s\n", "channel", co->channel);
write (fh, buf, strlen (buf));
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
val = G_STRUCT_MEMBER (guint8, co, chanopt[i].offset);
if (val != SET_DEFAULT)
{
snprintf (buf, sizeof (buf), "%s = %d\n", chanopt[i].name, val);
write (fh, buf, strlen (buf));
}
i++;
}
}
void
chanopt_save_all (void)
{
int i;
int num_saved;
int fh;
GSList *list;
chanopt_in_memory *co;
guint8 val;
if (!chanopt_list || !chanopt_changed)
{
return;
}
fh = xchat_open_file ("chanopt.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
if (fh == -1)
{
return;
}
for (num_saved = 0, list = chanopt_list; list; list = list->next)
{
co = list->data;
i = 0;
while (i < sizeof (chanopt) / sizeof (channel_options))
{
val = G_STRUCT_MEMBER (guint8, co, chanopt[i].offset);
/* not using global/default setting, must save */
if (val != SET_DEFAULT)
{
if (num_saved != 0)
write (fh, "\n", 1);
chanopt_save_one_channel (co, fh);
num_saved++;
goto cont;
}
i++;
}
cont:
g_free (co->network);
g_free (co->channel);
g_free (co);
}
close (fh);
/* we're quiting, no need to free */
/*g_slist_free (chanopt_list);
chanopt_list = NULL;
chanopt_open = FALSE;
chanopt_changed = FALSE;*/
}