/*
* XmNap A Motif napster client
*
* Copyright (C) 2000 Mats Peterson
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any comments/bug reports to
*
[email protected] (Mats Peterson)
*/
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/MessageB.h>
#include <Xm/Protocols.h>
#include <Xm/Notebook.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/TextF.h>
#include <Xm/SelectioB.h>
#include <Xm/ToggleB.h>
#include <Xm/Protocols.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <fnmatch.h>
#include "main.h"
#include "connect.h"
#include "command.h"
#include "search.h"
#include "config.h"
#include "configwin.h"
#include "transfer.h"
#include "shared.h"
#include "hotlist.h"
#include "input.h"
#include "msgbox.h"
#include "fsbox.h"
#ifdef USE_SOUND
#include "sound.h"
#endif
#include "util.h"
static String tmpPassWord;
static int tmpLinkType, tmpRegistered;
static String tmpMinLink;
static SERVER *tmpServers = NULL;
static SHAREDDIR *tmpSharedDirs = NULL;
static HOTLIST *tmpHotList = NULL;
static AUTOCOMMAND *tmpAutoCommands = NULL;
static int tmpAutoReconnect;
static int tmpShowPath;
static int tmpTimeOut;
static int tmpReconnTimeOut;
#ifdef USE_SOUND
#define LAST_PAGE 8
static String curSoundDir = NULL;
#else
#define LAST_PAGE 7
#endif
static int configChanged;
static int serverChanged;
static int sharedDirChanged;
static int hotListChanged;
static int autoCmdChanged;
static Widget configWin = NULL;
static void DestroyConfigWin(void)
{
if (configWin) {
XtUnmapWidget(XtParent(configWin));
XtDestroyWidget(XtParent(configWin));
configWin = curFocus = NULL;
}
}
static void ConfigCB(Widget w, XtPointer clientData,
XmPushButtonCallbackStruct *cbs)
{
SERVER *srv, *tmpSrv, *prevSrv = NULL;
SHAREDDIR *dir, *tmpDir, *prevDir = NULL;
SHARED *shared;
HOTLIST *hot, *tmpHot, *prevHot = NULL;
AUTOCOMMAND *cmd, *tmpCmd, *prevCmd = NULL;
String p, tmp;
Widget entry;
int i;
String userConfigEntryName[4] = {"*userConfig*userName",
"*userConfig*passWord",
"*userConfig*eMail",
"*userConfig*dataPort"};
String searchConfigEntryName[3] = {"*searchConfig*minBitrate",
"*searchConfig*minFreq",
"*searchConfig*maxFiles"};
String *userInfoField[3] = {&userInfo.userName, &userInfo.passWord,
&userInfo.eMail};
String *defSearchField[4] = {&defSearch.minBitrate, &defSearch.minFreq,
&defSearch.maxFiles, &defSearch.minLink};
#ifdef USE_SOUND
String soundConfigEntryName[NUM_SOUNDS] =
{"*soundConfig*chanMsgSound",
"*soundConfig*privMsgSound",
"*soundConfig*joinSound",
"*soundConfig*partSound"};
#endif
switch (cbs->reason) {
case XmCR_OK:
for (i = 0; i < 4; i++) {
if (i == 1)
continue;
entry = XtNameToWidget(w, userConfigEntryName[i]);
tmp = XmTextFieldGetString(entry);
if (i == 3) {
if (userInfo.dataPort != atoi(tmp)) {
userInfo.dataPort = atoi(tmp);
SetDataPort(userInfo.dataPort, 1);
configChanged = 1;
}
} else {
if (strcmp(*userInfoField[i], tmp)) {
XtFree(*userInfoField[i]);
*userInfoField[i] = XtNewString(tmp);
configChanged = 1;
}
}
XtFree(tmp);
}
for (i = 0; i < 3; i++) {
entry = XtNameToWidget(w, searchConfigEntryName[i]);
tmp = XmTextFieldGetString(entry);
if (strcmp(*defSearchField[i], tmp)) {
XtFree(*defSearchField[i]);
*defSearchField[i] = XtNewString(tmp);
configChanged = 1;
}
XtFree(tmp);
}
#ifdef USE_SOUND
for (i = 0; i < NUM_SOUNDS; i++) {
entry = XtNameToWidget(w, soundConfigEntryName[i]);
tmp = XmTextFieldGetString(entry);
if (strcmp(sound[i], tmp)) {
XtFree(sound[i]);
sound[i] = XtNewString(tmp);
configChanged = 1;
}
XtFree(tmp);
}
#endif
entry = XtNameToWidget(w, "*miscConfig*timeOut");
tmp = XmTextFieldGetString(entry);
if (timeOut != atoi(tmp)) {
timeOut = atoi(tmp);
configChanged = 1;
}
XtFree(tmp);
entry = XtNameToWidget(w, "*miscConfig*reconnTimeOut");
tmp = XmTextFieldGetString(entry);
if (reconnTimeOut != atoi(tmp)) {
reconnTimeOut = atoi(tmp);
configChanged = 1;
}
XtFree(tmp);
entry = XtNameToWidget(w, "*miscConfig*initDlDir");
tmp = XmTextFieldGetString(entry);
if (strcmp(initDlDir, tmp)) {
XtFree(initDlDir);
initDlDir = XtNewString(tmp);
configChanged = 1;
}
XtFree(tmp);
if (configChanged) {
SimpleMsg("Saving configuration");
WriteConfig();
SimpleMsgRemove();
}
break;
case XmCR_CANCEL:
case XmCR_PROTOCOLS:
XtFree(userInfo.passWord);
userInfo.passWord = XtNewString(tmpPassWord);
userInfo.linkType = tmpLinkType;
userInfo.registered = tmpRegistered;
XtFree(defSearch.minLink);
defSearch.minLink = XtNewString(tmpMinLink);
if (serverChanged) {
while (servers) {
XtFree(servers->name);
p = (String)servers;
servers = servers->next;
XtFree(p);
}
for (tmpSrv = tmpServers; tmpSrv; tmpSrv = tmpSrv->next) {
srv = XtNew(SERVER);
srv->name = XtNewString(tmpSrv->name);
srv->port = tmpSrv->port;
srv->meta = tmpSrv->meta;
srv->next = NULL;
if (! prevSrv)
servers = srv;
else
prevSrv->next = srv;
prevSrv = srv;
}
}
if (sharedDirChanged) {
while (sharedDirs) {
tmp = XtMalloc(PATH_MAX + 2);
sprintf(tmp, "%s*", sharedDirs->dirName);
for (shared = sharedFiles; shared; shared = shared->next) {
if (! fnmatch(tmp, shared->fileName, 0))
RemoveSharedFile(shared->fileName);
}
XtFree(tmp);
XtFree(sharedDirs->dirName);
p = (String)sharedDirs;
sharedDirs = sharedDirs->next;
XtFree(p);
}
for (tmpDir = tmpSharedDirs; tmpDir; tmpDir = tmpDir->next) {
dir = XtNew(SHAREDDIR);
dir->dirName = XtNewString(tmpDir->dirName);
dir->next = NULL;
if (! prevDir)
sharedDirs = dir;
else
prevDir->next = dir;
prevDir = dir;
(void)AddSharedFiles2(dir->dirName);
}
}
if (hotListChanged) {
while (hotList)
RemoveHotList(hotList->nick);
for (tmpHot = tmpHotList; tmpHot; tmpHot = tmpHot->next) {
hot = XtNew(HOTLIST);
hot->nick = XtNewString(tmpHot->nick);
hot->next = NULL;
if (! prevHot)
hotList = hot;
else
prevHot->next = hot;
prevHot = hot;
AddHotList(hot->nick, 1);
}
}
if (autoCmdChanged) {
while (autoCommands) {
XtFree(autoCommands->data);
p = (String)autoCommands;
autoCommands = autoCommands->next;
XtFree(p);
}
for (tmpCmd = tmpAutoCommands; tmpCmd; tmpCmd = tmpCmd->next) {
cmd = XtNew(AUTOCOMMAND);
cmd->data = XtNewString(tmpCmd->data);
cmd->next = NULL;
if (! prevCmd)
autoCommands = cmd;
else
prevCmd->next = cmd;
prevCmd = cmd;
}
}
autoReconnect = tmpAutoReconnect;
showPath = tmpShowPath;
timeOut = tmpTimeOut;
reconnTimeOut = tmpReconnTimeOut;
}
XtFree(tmpPassWord);
XtFree(tmpMinLink);
while (tmpServers) {
XtFree(tmpServers->name);
p = (String)tmpServers;
tmpServers = tmpServers->next;
XtFree(p);
}
while (tmpSharedDirs) {
XtFree(tmpSharedDirs->dirName);
p = (String)tmpSharedDirs;
tmpSharedDirs = tmpSharedDirs->next;
XtFree(p);
}
while (tmpHotList) {
XtFree(tmpHotList->nick);
p = (String)tmpHotList;
tmpHotList = tmpHotList->next;
XtFree(p);
}
while (tmpAutoCommands) {
XtFree(tmpAutoCommands->data);
p = (String)tmpAutoCommands;
tmpAutoCommands = tmpAutoCommands->next;
XtFree(p);
}
DestroyConfigWin();
}
static void ConfigEntryFocusCB(Widget w, XtPointer clientData,
XmAnyCallbackStruct *cbs) {
XtVaSetValues(w, XmNcursorPositionVisible, True, NULL);
}
static void ConfigEntryLosingFocusCB(Widget w, XtPointer clientData,
XmTextVerifyCallbackStruct *cbs) {
XtVaSetValues(w, XmNcursorPositionVisible, False, NULL);
}
static Widget ConfigForm(Widget parent, int page, String formName)
{
Widget form, title, rowCol;
Arg args[20];
int n;
form = XtVaCreateManagedWidget(formName,
xmFormWidgetClass, parent,
XmNmarginWidth, 15,
XmNmarginHeight, 15,
XmNnotebookChildType, XmPAGE,
XmNpageNumber, page,
NULL);
n = 0;
XtSetArg(args[n], XmNmarginHeight, 6); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
title = XmCreateLabel(form, "title", args, n);
XtManageChild(title);
rowCol = XtVaCreateManagedWidget("rowCol",
xmRowColumnWidgetClass, form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, title,
XmNmarginWidth, 0,
XmNtopOffset, 15,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
return form;
}
static Widget ConfigList(Widget parent, int page, String listName,
XtCallbackProc callback)
{
Widget list;
XmString xms;
Arg args[20];
int n;
String tmp;
n = 0;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
XtSetArg(args[n], XmNnotebookChildType, XmPAGE); n++;
XtSetArg(args[n], XmNpageNumber, page); n++;
list = XmCreateSelectionBox(parent, listName, args, n);
XtManageChild(list);
XtAddCallback (list, XmNokCallback,
(XtCallbackProc)callback, NULL);
XtVaGetValues(list, XmNapplyLabelString, &xms, NULL);
XmStringGetLtoR(xms, XmFONTLIST_DEFAULT_TAG, &tmp);
if (strlen(tmp)) {
XtManageChild(XtNameToWidget(list, "Apply"));
XtAddCallback (list, XmNapplyCallback,
(XtCallbackProc)callback, NULL);
}
XtFree(tmp);
XmStringFree(xms);
XtAddCallback (list, XmNcancelCallback,
(XtCallbackProc)callback, NULL);
XtUnmanageChild(XtNameToWidget(list, "Help"));
XtUnmanageChild(XtNameToWidget(list, "Text"));
XtUnmanageChild(XtNameToWidget(list, "Selection"));
return list;
}
static void UserConfigPasswordCB(Widget w, XtPointer clientData,
XtPointer callData)
{
char *new;
int len;
XmTextVerifyCallbackStruct *cbs =
(XmTextVerifyCallbackStruct *)callData;
if (cbs->startPos < cbs->currInsert) { /* backspace */
cbs->endPos = strlen(userInfo.passWord); /* delete from here to end */
userInfo.passWord[cbs->startPos] = 0; /* backspace--terminate */
return;
}
if (cbs->startPos < cbs->endPos) { /* don't allow delete */
cbs->doit = False;
return;
}
if (cbs->text->length > 1) {
cbs->doit = False; /* don't allow "paste" operations */
return; /* make the user *type* the password! */
}
new = XtMalloc(cbs->endPos + 2); /* new char + NULL terminator */
if (userInfo.passWord) {
strcpy(new, userInfo.passWord);
XtFree(userInfo.passWord);
} else
new[0] = NULL;
userInfo.passWord = new;
strncat(userInfo.passWord, cbs->text->ptr, cbs->text->length);
userInfo.passWord[cbs->endPos + cbs->text->length] = 0;
for (len = 0; len < cbs->text->length; len++)
cbs->text->ptr[len] = '*';
configChanged = 1;
}
static void UserConfigLinkCB(Widget w, XtPointer clientData,
XtPointer cbs)
{
userInfo.linkType = (int)clientData;
configChanged = 1;
}
static void UserConfigRegCB(Widget w, XtPointer clientData,
XmToggleButtonCallbackStruct *cbs)
{
userInfo.registered = (cbs->set == XmSET) ? 1 : 0;
configChanged = 1;
}
static void UserConfig(Widget parent)
{
String values[6];
char dataPort[10];
Widget pageForm, rowCol, form, label, entry = NULL;
Widget linkMenu, regToggle;
Arg args[20];
XmString toggleString;
XmString optLabel[11];
int i, j, n;
Dimension labelWidth, labelMaxWidth = 0;
char labelName[20];
String entryName[] = {"userName", "passWord", "eMail", "dataPort"};
String starPassWord;
pageForm = ConfigForm(parent, 1, "userConfig");
rowCol = XtNameToWidget(pageForm, "rowCol");
starPassWord = XtMalloc(strlen(userInfo.passWord) + 2);
for (i = 0; i < strlen(userInfo.passWord); i++)
starPassWord[i] = '*';
starPassWord[i] = '\0';
values[0] = userInfo.userName;
values[1] = starPassWord;
values[2] = userInfo.eMail;
sprintf(dataPort, "%d", userInfo.dataPort);
values[3] = dataPort;
for (i = 0; i < 6; i++) {
form = XtVaCreateWidget("form", xmFormWidgetClass,
rowCol, NULL);
sprintf(labelName, "label_%d", i);
n = 0;
XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
XtSetArg(args[n], XmNmarginHeight, 6); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
label = XmCreateLabel(form, labelName, args, n);
XtManageChild(label);
XtVaGetValues(label, XmNwidth, &labelWidth, NULL);
if (labelWidth > labelMaxWidth)
labelMaxWidth = labelWidth;
if (i == 4) {
for (j = 0; j < 11; j++)
optLabel[j] = XmStringCreateLocalized (linkStr[j]);
linkMenu = XmVaCreateSimpleOptionMenu (form, "linkMenu",
NULL, 0, userInfo.linkType, UserConfigLinkCB,
XmVaPUSHBUTTON, optLabel[0], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[1], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[2], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[3], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[4], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[5], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[6], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[7], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[8], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[9], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[10], NULL, NULL, NULL,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, label,
XmNleftOffset, 20,
XmNmarginWidth, 0,
XmNmarginHeight, 0,
NULL);
for (j = 0; j < 11; j++)
XmStringFree(optLabel[j]);
XtUnmanageChild(XtNameToWidget(linkMenu, "OptionLabel"));
XtManageChild (linkMenu);
} else if (i == 5) {
toggleString = XmStringCreateLocalized(" ");
regToggle = XtVaCreateManagedWidget("regToggle",
xmToggleButtonWidgetClass, form,
XmNlabelString, toggleString,
XmNindicatorOn, XmINDICATOR_CROSS_BOX,
XmNset, userInfo.registered ? XmSET : XmUNSET,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, label,
XmNleftOffset, 20,
NULL);
XmStringFree(toggleString);
XtAddCallback(regToggle, XmNvalueChangedCallback,
(XtCallbackProc)UserConfigRegCB, NULL);
} else {
n = 0;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
XtSetArg(args[n], XmNmarginWidth, 5); n++;
XtSetArg(args[n], XmNmarginHeight, 2); n++;
XtSetArg(args[n], XmNcolumns, 30); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, label); n++;
XtSetArg(args[n], XmNleftOffset, 20); n++;
entry = XmCreateTextField(form, entryName[i], args, n);
XtManageChild(entry);
XmTextFieldSetString(entry, values[i]);
XtAddCallback(entry, XmNfocusCallback,
(XtCallbackProc)ConfigEntryFocusCB, NULL);
XtAddCallback(entry, XmNlosingFocusCallback,
(XtCallbackProc)ConfigEntryLosingFocusCB, NULL);
if (i == 1) {
XtAddCallback(entry, XmNmodifyVerifyCallback,
(XtCallbackProc)UserConfigPasswordCB, NULL);
}
}
XtManageChild(form);
}
for (i = 0; i < 6; i++) {
sprintf(labelName, "form.label_%d", i);
XtVaSetValues(XtNameToWidget(rowCol, labelName),
XmNwidth, labelMaxWidth, NULL);
}
XtFree(starPassWord);
}
static void SearchConfigLinkCB(Widget w, XtPointer clientData,
XtPointer cbs)
{
XtFree(defSearch.minLink);
defSearch.minLink = XtMalloc(5);
sprintf(defSearch.minLink, "%d", (int)clientData);
configChanged = 1;
}
static void SearchConfig(Widget parent)
{
String values[4];
Widget pageForm, rowCol, form, label, entry = NULL, linkMenu;
Arg args[20];
XmString optLabel[11];
int i, j, n;
Dimension labelWidth, labelMaxWidth = 0;
char labelName[20];
String entryName[] = {"minBitrate", "minFreq", "maxFiles"};
pageForm = ConfigForm(parent, 2, "searchConfig");
rowCol = XtNameToWidget(pageForm, "rowCol");
values[0] = defSearch.minBitrate;
values[1] = defSearch.minFreq;
values[2] = defSearch.maxFiles;
for (i = 0; i < 4; i++) {
form = XtVaCreateWidget("form", xmFormWidgetClass,
rowCol, NULL);
sprintf(labelName, "label_%d", i);
n = 0;
XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
XtSetArg(args[n], XmNmarginHeight, 6); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
label = XmCreateLabel(form, labelName, args, n);
XtManageChild(label);
XtVaGetValues(label, XmNwidth, &labelWidth, NULL);
if (labelWidth > labelMaxWidth)
labelMaxWidth = labelWidth;
if (i == 3) {
for (j = 0; j < 11; j++)
optLabel[j] = XmStringCreateLocalized (linkStr[j]);
linkMenu = XmVaCreateSimpleOptionMenu (form, "linkMenu",
NULL, 0, atoi(defSearch.minLink), SearchConfigLinkCB,
XmVaPUSHBUTTON, optLabel[0], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[1], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[2], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[3], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[4], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[5], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[6], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[7], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[8], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[9], NULL, NULL, NULL,
XmVaPUSHBUTTON, optLabel[10], NULL, NULL, NULL,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, label,
XmNleftOffset, 20,
XmNmarginWidth, 0,
XmNmarginHeight, 0,
NULL);
for (j = 0; j < 11; j++)
XmStringFree(optLabel[j]);
XtUnmanageChild(XtNameToWidget(linkMenu, "OptionLabel"));
XtManageChild (linkMenu);
} else {
n = 0;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
XtSetArg(args[n], XmNmarginWidth, 5); n++;
XtSetArg(args[n], XmNmarginHeight, 2); n++;
XtSetArg(args[n], XmNcolumns, 10); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, label); n++;
XtSetArg(args[n], XmNleftOffset, 20); n++;
entry = XmCreateTextField(form, entryName[i], args, n);
XtManageChild(entry);
XmTextFieldSetString(entry, values[i]);
XtAddCallback(entry, XmNfocusCallback,
(XtCallbackProc)ConfigEntryFocusCB, NULL);
XtAddCallback(entry, XmNlosingFocusCallback,
(XtCallbackProc)ConfigEntryLosingFocusCB, NULL);
}
XtManageChild(form);
}
for (i = 0; i < 4; i++) {
sprintf(labelName, "form.label_%d", i);
XtVaSetValues(XtNameToWidget(rowCol, labelName),
XmNwidth, labelMaxWidth, NULL);
}
}
static void UpdateServerList(Widget list)
{
String tmp = XtMalloc(256);
int numServers, i;
XmString *str;
SERVER *srv;
String srvType[2] = {"Normal", "Meta"};
for (numServers = 0, srv = servers; srv;
numServers++, srv = srv->next);
str = (XmString*)XtMalloc(numServers * sizeof(XmString));
for (i = 0, srv = servers; i < numServers; i++, srv = srv->next) {
sprintf(tmp, "%-30.29s%-10d%s",
srv->name, srv->port, srvType[srv->meta]);
str[i] = XmStringCreateLocalized(tmp);
}
XtVaSetValues(list,
XmNlistItems, str,
XmNlistItemCount, numServers,
NULL);
for (i = 0; i < numServers; i++)
XmStringFree (str[i]);
XtFree((String)str);
XtFree(tmp);
}
static void SrvListCB(Widget w, XtPointer clientData,
XmSelectionBoxCallbackStruct *cbs)
{
Widget list, shell;
int i, *pos;
SERVER *newSrv, *srv, *prevSrv = NULL;
String srvString, srvName, portString, metaString;
XmPushButtonCallbackStruct cbs2;
switch (cbs->reason) {
case XmCR_OK:
list = XtNameToWidget(w, "ItemsListSW.ItemsList");
XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
if (! pos)
return;
cbs2.reason = XmCR_OK;
for (shell = w; ! XtIsShell(shell); shell = XtParent(shell));
XtCallCallbacks(XtNameToWidget(shell, "configWin"),
XmNokCallback, (XtPointer)&cbs2);
for (i = 0, srv = servers; i < ((*pos) - 1);
i++, srv = srv->next);
if (srvConn)
Disconnect("");
Connect(srv->name, srv->port, srv->meta, 1);
return;
case XmCR_APPLY:
srvString = GetInput("Server (name:port:meta)", "", 30);
if (! strlen(srvString))
return;
if (! SplitServer(srvString, &srvName, &portString,
&metaString)) {
ErrMsg("Invalid server format");
return;
}
newSrv = XtNew(SERVER);
newSrv->name = XtNewString(srvName);
newSrv->port = atoi(portString);
newSrv->meta = atoi(metaString);
newSrv->next = NULL;
if (! servers)
servers = newSrv;
else {
for (srv = servers; srv->next; srv = srv->next);
srv->next = newSrv;
}
break;
case XmCR_CANCEL:
list = XtNameToWidget(w, "ItemsListSW.ItemsList");
XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
if (! pos)
return;
for (i = 0, srv = servers; i < ((*pos) - 1);
i++, srv = srv->next) {
prevSrv = srv;
}
if (prevSrv) {
prevSrv->next = srv->next;
} else {
servers = servers->next;
}
XtFree(srv->name);
XtFree((char*)srv);
}
if (servers) {
if (curServer.name)
XtFree(curServer.name);
curServer.name = XtNewString(servers->name);
curServer.port = servers->port;
curServer.meta = servers->meta;
}
UpdateServerList(w);
serverChanged = 1;
configChanged = 1;
}
static void ServerConfig(Widget parent)
{
Widget serverList;
serverList = ConfigList(parent, 3, "serverConfig",
(XtCallbackProc)SrvListCB);
if (! servers)
return;
UpdateServerList(serverList);
}
static void UpdateSharedDirList(Widget list)
{
int numDirs, i;
XmString *str;
SHAREDDIR *dir;
for (numDirs = 0, dir = sharedDirs; dir;
numDirs++, dir = dir->next);
str = (XmString*)XtMalloc(numDirs * sizeof(XmString));
for (i = 0, dir = sharedDirs; i < numDirs; i++, dir = dir->next)
str[i] = XmStringCreateLocalized(dir->dirName);
XtVaSetValues(list,
XmNlistItems, str,
XmNlistItemCount, numDirs,
NULL);
for (i = 0; i < numDirs; i++)
XmStringFree (str[i]);
XtFree((String)str);
}
static void SharedDirListCB(Widget w, XtPointer clientData,
XmSelectionBoxCallbackStruct *cbs)
{
Widget list;
int i, *pos;
SHAREDDIR *dir;
switch (cbs->reason) {
case XmCR_OK:
if (! AddSharedFiles())
return;
break;
case XmCR_CANCEL:
list = XtNameToWidget(w, "ItemsListSW.ItemsList");
XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
if (! pos)
return;
for (i = 0, dir = sharedDirs; i < ((*pos) - 1);
i++, dir = dir->next);
if (! RemoveSharedFiles(dir->dirName))
return;
}
UpdateSharedDirList(w);
sharedDirChanged = 1;
configChanged = 1;
}
static void SharedDirConfig(Widget parent)
{
Widget sharedDirList;
sharedDirList = ConfigList(parent, 4, "sharedConfig",
(XtCallbackProc)SharedDirListCB);
if (! sharedDirs)
return;
UpdateSharedDirList(sharedDirList);
}
static void UpdateHotList(Widget list)
{
int numHot, i;
XmString *str;
HOTLIST *hot;
for (numHot = 0, hot = hotList; hot;
numHot++, hot = hot->next);
str = (XmString*)XtMalloc(numHot * sizeof(XmString));
for (i = 0, hot = hotList; i < numHot; i++, hot = hot->next)
str[i] = XmStringCreateLocalized(hot->nick);
XtVaSetValues(list,
XmNlistItems, str,
XmNlistItemCount, numHot,
NULL);
for (i = 0; i < numHot; i++)
XmStringFree (str[i]);
XtFree((String)str);
}
static void HotListCB(Widget w, XtPointer clientData,
XmSelectionBoxCallbackStruct *cbs)
{
Widget list;
int *pos;
String nick;
switch (cbs->reason) {
case XmCR_OK:
nick = GetInput("User", "", 30);
if (! strlen(nick))
return;
AddHotList(nick, 1);
break;
case XmCR_CANCEL:
list = XtNameToWidget(w, "ItemsListSW.ItemsList");
XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
if (! pos)
return;
RemoveHotList2((*pos) - 1);
}
UpdateHotList(w);
hotListChanged = 1;
configChanged = 1;
}
static void HotListConfig(Widget parent)
{
Widget hotList;
hotList = ConfigList(parent, 5, "hotlistConfig",
(XtCallbackProc)HotListCB);
if (! hotList)
return;
UpdateHotList(hotList);
}
static void UpdateAutoCmdList(Widget list)
{
int numCmds, i;
XmString *str;
AUTOCOMMAND *cmd;
for (numCmds = 0, cmd = autoCommands; cmd;
numCmds++, cmd = cmd->next);
str = (XmString*)XtMalloc(numCmds * sizeof(XmString));
for (i = 0, cmd = autoCommands; i < numCmds; i++, cmd = cmd->next)
str[i] = XmStringCreateLocalized(cmd->data);
XtVaSetValues(list,
XmNlistItems, str,
XmNlistItemCount, numCmds,
NULL);
for (i = 0; i < numCmds; i++)
XmStringFree (str[i]);
XtFree((String)str);
}
static void AutoCmdListCB(Widget w, XtPointer clientData,
XmSelectionBoxCallbackStruct *cbs)
{
Widget list;
int i, *pos;
AUTOCOMMAND *newCmd, *cmd, *prevCmd = NULL;
String cmdString;
switch (cbs->reason) {
case XmCR_OK:
cmdString = GetInput("Command", "", 40);
if (! strlen(cmdString))
return;
newCmd = XtNew(AUTOCOMMAND);
newCmd->data = XtNewString(cmdString);
newCmd->next = NULL;
if (! autoCommands)
autoCommands = newCmd;
else {
for (cmd = autoCommands; cmd->next; cmd = cmd->next);
cmd->next = newCmd;
}
break;
case XmCR_CANCEL:
list = XtNameToWidget(w, "ItemsListSW.ItemsList");
XtVaGetValues(list, XmNselectedPositions, &pos, NULL);
if (! pos)
return;
for (i = 0, cmd = autoCommands; i < ((*pos) - 1);
i++, cmd = cmd->next) {
prevCmd = cmd;
}
if (prevCmd)
prevCmd->next = cmd->next;
else
autoCommands = autoCommands->next;
XtFree(cmd->data);
XtFree((char*)cmd);
}
UpdateAutoCmdList(w);
autoCmdChanged = 1;
configChanged = 1;
}
static void AutoCmdConfig(Widget parent)
{
Widget autoCmdList;
autoCmdList = ConfigList(parent, 6, "autoCmdConfig",
(XtCallbackProc)AutoCmdListCB);
if (! autoCommands)
return;
UpdateAutoCmdList(autoCmdList);
}
#ifdef USE_SOUND
static void SoundBtnCB(Widget w, XtPointer clientData,
XmPushButtonCallbackStruct *cbs)
{
Widget entry = (Widget)clientData;
String tmp, dir, tail, name;
if (! curSoundDir)
curSoundDir = XtNewString(getenv("HOME"));
tmp = XmTextFieldGetString(entry);
if ((tail = strrchr(tmp, '/'))) {
dir = GetDir(tmp);
tail += 1;
} else {
dir = XtNewString(curSoundDir);
tail = "";
}
name = OpenFile(dir, tail);
if (! *name)
goto exit;
if (CheckWav(name) == -1)
goto exit;
XmTextFieldSetString(entry, name);
XtFree(curSoundDir);
curSoundDir = GetDir(name);
exit:
XtFree(tmp);
XtFree(dir);
}
static void SoundConfig(Widget parent)
{
Widget pageForm, rowCol, form, label, entry = NULL, btn;
Arg args[20];
int i, n;
Dimension labelWidth, labelMaxWidth = 0;
char labelName[20], btnName[20];
String entryName[] = {"chanMsgSound", "privMsgSound",
"joinSound", "partSound"};
pageForm = ConfigForm(parent, 7, "soundConfig");
rowCol = XtNameToWidget(pageForm, "rowCol");
for (i = 0; i < NUM_SOUNDS; i++) {
form = XtVaCreateWidget("form", xmFormWidgetClass,
rowCol, NULL);
sprintf(labelName, "label_%d", i);
n = 0;
XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
XtSetArg(args[n], XmNmarginHeight, 6); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
label = XmCreateLabel(form, labelName, args, n);
XtManageChild(label);
XtVaGetValues(label, XmNwidth, &labelWidth, NULL);
if (labelWidth > labelMaxWidth)
labelMaxWidth = labelWidth;
sprintf(btnName, "button_%d", i);
btn = XtVaCreateManagedWidget(btnName,
xmPushButtonWidgetClass, form,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
n = 0;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
XtSetArg(args[n], XmNmarginWidth, 5); n++;
XtSetArg(args[n], XmNmarginHeight, 2); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, label); n++;
XtSetArg(args[n], XmNleftOffset, 20); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, btn); n++;
XtSetArg(args[n], XmNrightOffset, 10); n++;
XtSetArg(args[n], XmNcolumns, 25); n++;
entry = XmCreateTextField(form, entryName[i], args, n);
XtAddCallback(btn, XmNactivateCallback,
(XtCallbackProc)SoundBtnCB, (XtPointer)entry);
XtAddCallback(entry, XmNfocusCallback,
(XtCallbackProc)ConfigEntryFocusCB, NULL);
XtAddCallback(entry, XmNlosingFocusCallback,
(XtCallbackProc)ConfigEntryLosingFocusCB, NULL);
XtManageChild(entry);
XmTextFieldSetString(entry, sound[i]);
XtManageChild(form);
}
for (i = 0; i < NUM_SOUNDS; i++) {
sprintf(labelName, "form.label_%d", i);
XtVaSetValues(XtNameToWidget(rowCol, labelName),
XmNwidth, labelMaxWidth, NULL);
}
}
#endif
static void MiscConfigToggleCB(Widget w, XtPointer clientData,
XmToggleButtonCallbackStruct *cbs)
{
if (! (strcmp(XtName(w), "autoReconnectToggle")))
autoReconnect = (cbs->set == XmSET) ? 1 : 0;
else
showPath = (cbs->set == XmSET) ? 1 : 0;
configChanged = 1;
}
static void DirBtnCB(Widget w, XtPointer clientData,
XmPushButtonCallbackStruct *cbs)
{
Widget entry = (Widget)clientData;
String tmp, dir;
tmp = XmTextFieldGetString(entry);
dir = ChooseDir(tmp);
XtFree(tmp);
if (! strlen(dir))
return;
XmTextFieldSetString(entry, dir);
}
static void MiscConfig(Widget parent)
{
String values[5];
char timeOutStr[5], reconnTimeOutStr[5];
Widget pageForm, rowCol, form, label, entry = NULL;
Widget toggle, dirBtn;
Arg args[20];
XmString toggleString;
int i, n;
Dimension labelWidth, labelMaxWidth = 0;
char labelName[20];
String toggleName[] = {"autoReconnectToggle", "showPathToggle"};
String entryName[] = {"timeOut", "reconnTimeOut", "initDlDir"};
pageForm = ConfigForm(parent, LAST_PAGE, "miscConfig");
rowCol = XtNameToWidget(pageForm, "rowCol");
sprintf(timeOutStr, "%d", timeOut);
sprintf(reconnTimeOutStr, "%d", reconnTimeOut);
values[2] = timeOutStr;
values[3] = reconnTimeOutStr;
values[4] = initDlDir;
for (i = 0; i < 5; i++) {
form = XtVaCreateWidget("form", xmFormWidgetClass,
rowCol, NULL);
sprintf(labelName, "label_%d", i);
n = 0;
XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
XtSetArg(args[n], XmNmarginHeight, 6); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
label = XmCreateLabel(form, labelName, args, n);
XtManageChild(label);
XtVaGetValues(label, XmNwidth, &labelWidth, NULL);
if (labelWidth > labelMaxWidth)
labelMaxWidth = labelWidth;
if (i < 2) {
toggleString = XmStringCreateLocalized(" ");
toggle = XtVaCreateManagedWidget(toggleName[i],
xmToggleButtonWidgetClass, form,
XmNlabelString, toggleString,
XmNindicatorOn, XmINDICATOR_CROSS_BOX,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, label,
XmNleftOffset, 20,
NULL);
XmStringFree(toggleString);
if (i == 0) {
XtVaSetValues(toggle,
XmNset, autoReconnect ? XmSET : XmUNSET, NULL);
} else {
XtVaSetValues(toggle,
XmNset, showPath ? XmSET : XmUNSET, NULL);
}
XtAddCallback(toggle, XmNvalueChangedCallback,
(XtCallbackProc)MiscConfigToggleCB, NULL);
} else {
n = 0;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
XtSetArg(args[n], XmNmarginWidth, 5); n++;
XtSetArg(args[n], XmNmarginHeight, 2); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, label); n++;
XtSetArg(args[n], XmNleftOffset, 20); n++;
if (i == 4) {
dirBtn = XtVaCreateManagedWidget("dirBtn",
xmPushButtonWidgetClass, form,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, dirBtn); n++;
XtSetArg(args[n], XmNrightOffset, 10); n++;
XtSetArg(args[n], XmNcolumns, 20); n++;
entry = XmCreateTextField(form, entryName[i - 2], args, n);
XtAddCallback(dirBtn, XmNactivateCallback,
(XtCallbackProc)DirBtnCB, (XtPointer)entry);
} else {
XtSetArg(args[n], XmNcolumns, 5); n++;
entry = XmCreateTextField(form, entryName[i - 2], args, n);
}
XtAddCallback(entry, XmNfocusCallback,
(XtCallbackProc)ConfigEntryFocusCB, NULL);
XtAddCallback(entry, XmNlosingFocusCallback,
(XtCallbackProc)ConfigEntryLosingFocusCB, NULL);
XtManageChild(entry);
XmTextFieldSetString(entry, values[i]);
}
XtManageChild(form);
}
for (i = 0; i < 5; i++) {
sprintf(labelName, "form.label_%d", i);
XtVaSetValues(XtNameToWidget(rowCol, labelName),
XmNwidth, labelMaxWidth, NULL);
}
}
static void Backup(void)
{
SERVER *srv, *tmpSrv, *prevSrv = NULL;
SHAREDDIR *dir, *tmpDir, *prevDir = NULL;
HOTLIST *hot, *tmpHot, *prevHot = NULL;
AUTOCOMMAND *cmd, *tmpCmd, *prevCmd = NULL;
tmpPassWord = XtNewString(userInfo.passWord);
tmpLinkType = userInfo.linkType;
tmpRegistered = userInfo.registered;
tmpMinLink = XtNewString(defSearch.minLink);
for (srv = servers; srv; srv = srv->next) {
tmpSrv = XtNew(SERVER);
tmpSrv->name = XtNewString(srv->name);
tmpSrv->port = srv->port;
tmpSrv->meta = srv->meta;
tmpSrv->next = NULL;
if (! prevSrv)
tmpServers = tmpSrv;
else
prevSrv->next = tmpSrv;
prevSrv = tmpSrv;
}
for (dir = sharedDirs; dir; dir = dir->next) {
tmpDir = XtNew(SHAREDDIR);
tmpDir->dirName = XtNewString(dir->dirName);
tmpDir->next = NULL;
if (! prevDir)
tmpSharedDirs = tmpDir;
else
prevDir->next = tmpDir;
prevDir = tmpDir;
}
for (hot = hotList; hot; hot = hot->next) {
tmpHot = XtNew(HOTLIST);
tmpHot->nick = XtNewString(hot->nick);
tmpHot->next = NULL;
if (! prevHot)
tmpHotList = tmpHot;
else
prevHot->next = tmpHot;
prevHot = tmpHot;
}
for (cmd = autoCommands; cmd; cmd = cmd->next) {
tmpCmd = XtNew(AUTOCOMMAND);
tmpCmd->data = XtNewString(cmd->data);
tmpCmd->next = NULL;
if (! prevCmd)
tmpAutoCommands = tmpCmd;
else
prevCmd->next = tmpCmd;
prevCmd = tmpCmd;
}
tmpAutoReconnect = autoReconnect;
tmpShowPath = showPath;
tmpTimeOut = timeOut;
tmpReconnTimeOut = reconnTimeOut;
}
void ConfigWin(int pageNum)
{
Widget shell, configNB;
Arg args[20];
#ifdef USE_SOUND
String pageName[] = {"userConfig", "searchConfig",
"serverConfig", "sharedConfig",
"hotlistConfig", "autoCmdConfig",
"soundConfig", "miscConfig", NULL};
#else
String pageName[] = {"userConfig", "searchConfig",
"serverConfig", "sharedConfig",
"hotlistConfig", "autoCmdConfig",
"miscConfig", NULL};
#endif
String tabName;
int i, n;
DestroyConfigWin();
shell = XtVaCreatePopupShell("configWin_popup",
topLevelShellWidgetClass, topLevel,
XmNiconPixmap, napPix,
NULL);
n = 0;
XtSetArg(args[n], XmNautoUnmanage, False); n++;
XtSetArg(args[n], XmNdefaultPosition, False); n++;
XtSetArg(args[n], XmNnoResize, True); n++;
XtSetArg(args[n], XmNmessageAlignment, XmALIGNMENT_CENTER); n++;
configWin = XmCreateMessageBox(shell, "configWin", args, n);
XtUnmanageChild(XtNameToWidget(configWin, "Help"));
n = 0;
XtSetArg(args[n], XmNbindingType, XmNONE); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
configNB = XmCreateNotebook(configWin, "configNB", args, n);
XtManageChild(configNB);
XtAddCallback(configWin, XmNokCallback,
(XtCallbackProc)ConfigCB, NULL);
XtAddCallback(configWin, XmNcancelCallback,
(XtCallbackProc)ConfigCB, NULL);
XmAddWMProtocolCallback(XtParent(configWin),
XmInternAtom(XtDisplay(configWin), "WM_DELETE_WINDOW", False),
(XtCallbackProc)ConfigCB, NULL);
XtAddCallback(configWin, XmNfocusCallback,
(XtCallbackProc)FocusCB, NULL);
XmAddWMProtocolCallback(topLevel,
XmInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW", False),
(XtCallbackProc)ConfigCB, NULL);
for (i = 0; pageName[i]; i++) {
tabName = XtMalloc(strlen(pageName[i]) + sizeof("Tab") + 1);
sprintf(tabName, "%sTab", pageName[i]);
(void)XtVaCreateManagedWidget(tabName,
xmPushButtonWidgetClass, configNB,
XmNnotebookChildType, XmMAJOR_TAB,
XmNpageNumber, i + 1,
NULL);
XtFree(tabName);
}
Backup();
UserConfig(configNB);
SearchConfig(configNB);
ServerConfig(configNB);
SharedDirConfig(configNB);
HotListConfig(configNB);
AutoCmdConfig(configNB);
#ifdef USE_SOUND
SoundConfig(configNB);
#endif
MiscConfig(configNB);
serverChanged = sharedDirChanged = hotListChanged =
autoCmdChanged = configChanged = 0;
XtVaSetValues(configNB, XmNinitialFocus,
XtNameToWidget(configNB, pageName[pageNum - 1]), NULL);
XtVaSetValues(configWin, XmNinitialFocus, configNB,
NULL);
XtManageChild(configWin);
XtPopup(shell, XtGrabNone);
XtVaSetValues(configNB, XmNcurrentPageNumber, pageNum, NULL);
}