/*
* 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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <regex.h>
#include <errno.h>
#include "chat.h"
#include "main.h"
#include "msgbox.h"
char* ReadErr(int r)
{
if (r == 0)
return "EOF";
else
return strerror(errno);
}
int ReadChars(int fd, void *ptr, int toRead)
{
char *p = (char*)ptr;
int copiedNow, copied;
for (copied = 0; (unsigned)toRead > 0; ) {
copiedNow = read(fd, p, toRead);
if (copiedNow <= 0) {
if (copiedNow == -1) {
if (errno != EAGAIN)
return copiedNow;
copiedNow = 0;
} else
return copiedNow;
}
copied += copiedNow;
toRead -= copiedNow;
p += copiedNow;
XmUpdateDisplay(topLevel);
if ((unsigned)toRead > 0)
usleep(1000);
}
return copied;
}
int WriteChars(int fd, void *ptr, int toWrite)
{
char *p = (char*)ptr;
int copiedNow, copied;
for (copied = 0; (unsigned)toWrite > 0; ) {
copiedNow = write(fd, p, toWrite);
if (copiedNow < 0) {
if (errno != EAGAIN)
return copiedNow;
copiedNow = 0;
}
copied += copiedNow;
toWrite -= copiedNow;
p += copiedNow;
XmUpdateDisplay(topLevel);
if ((unsigned)toWrite > 0)
usleep(1000);
}
return copied;
}
PRIV* FindPrivByNick(String nick)
{
PRIV *p;
for (p = privs; p; p = p->next) {
if (! strcmp(p->nick, nick))
break;
}
return p;
}
PRIV* FindPrivByWin(Widget w)
{
PRIV *p;
for (p = privs; p; p = p->next) {
if (p->w == w)
break;
}
return p;
}
CHAN* FindChanByName(String channel)
{
CHAN *c;
for (c = channels; c; c = c->next) {
if (! strcmp(c->name, channel))
break;
}
return c;
}
CHAN* FindChanByWin(Widget w)
{
CHAN *c;
for (c = channels; c; c = c->next) {
if (c->w == w)
break;
}
return c;
}
int CmdMatch(String s, String cmd, int len)
{
if (strlen(s) < len)
return 0;
return !strncmp(s, cmd, strlen(s));
}
int SplitServer(String s, String *name, String *port, String *meta)
{
String p = s;
while (isspace(*p))
p++;
if (! *p)
return 0;
*name = p;
if (! (p = strchr(*name, ':')))
return 0;
*p++ = 0;
*port = p;
if (! (p = strchr(*port, ':')))
return 0;
*p++ = 0;
*meta = p;
return 1;
}
String GetFileTail(String fileName)
{
String p, p2, tail;
if ((p = strrchr(fileName, '\\'))) {
tail = p;
*p = '\0';
if ((p2 = strrchr(fileName, '\\')))
tail = p2;
*p = '\\';
} else if ((p = strrchr(fileName, '/'))) {
tail = p;
*p = '\0';
if ((p2 = strrchr(fileName, '/')))
tail = p2;
*p = '/';
} else
tail = fileName;
if (tail != fileName)
tail++;
return XtNewString(tail);
}
String GetDir(String fileName)
{
String tail, dir;
int dirLen;
tail = strrchr(fileName, '/');
dirLen = tail - fileName;
if (dirLen) {
dir = XtCalloc(dirLen + 1, 1);
strncpy(dir, fileName, dirLen);
} else
dir = XtNewString("/");
return dir;
}
int RegEx(String s, String regExpr, int nmatch, regmatch_t pmatch[])
{
regex_t reg;
char rbuf[256];
int r;
if((r = regcomp(®, regExpr, REG_EXTENDED))) {
regerror(r, ®, rbuf, 256);
ErrMsg(rbuf);
regfree(®);
return -1;
}
r = regexec(®, s, nmatch, pmatch, 0);
regfree(®);
return r ? 0 : 1;
}
void CenterDialog(Widget d)
{
Dimension width, height, scrWidth, scrHeight;
Widget topLevel = XtParent(d);
XtVaSetValues(topLevel, XmNmappedWhenManaged, False, NULL);
XtManageChild(d);
XtVaGetValues(d, XmNwidth, &width, XmNheight, &height, NULL);
scrWidth = WidthOfScreen(XtScreen(d));
scrHeight = HeightOfScreen(XtScreen(d));
XtVaSetValues(d, XmNx, (scrWidth / 2) - (width / 2),
XmNy, (scrHeight / 2) - (height / 2), NULL);
XtVaSetValues(topLevel, XmNmappedWhenManaged, True, NULL);
}
/*
* This procedure will ensure that, if a dialog window is being mapped,
* its contents become visible before returning. It is intended to be
* used just before a bout of computing that doesn't service the display.
* You should still call XmUpdateDisplay() at intervals during this
* computing if possible.
*
* The monitoring of window states is necessary because attempts to map
* the dialog are redirected to the window manager (if there is one) and
* this introduces a significant delay before the window is actually mapped
* and exposed. This code works under mwm, twm, uwm, and no-wm. It
* doesn't work (but doesn't hang) with olwm if the mainwindow is iconified.
*
* The argument to ForceDialog is any widget in the dialog (often it
* will be the BulletinBoard child of a DialogShell).
*/
void ForceDialog(Widget w)
{
Widget diashell, topshell;
Window diawindow, topwindow;
Display *dpy;
XWindowAttributes xwa;
XEvent event;
XtAppContext cxt;
/* Locate the shell we are interested in. In a particular instance, you
* may know these shells already.
*/
for (diashell = w; !XtIsShell(diashell);
diashell = XtParent(diashell));
/* Locate its primary window's shell (which may be the same) */
for (topshell = diashell; !XtIsTopLevelShell(topshell);
topshell = XtParent(topshell));
if (XtIsRealized(diashell) && XtIsRealized(topshell)) {
dpy = XtDisplay(topshell);
diawindow = XtWindow(diashell);
topwindow = XtWindow(topshell);
cxt = XtWidgetToApplicationContext(diashell);
/* Wait for the dialog to be mapped. It's guaranteed to become so unless... */
while (XGetWindowAttributes(dpy, diawindow, &xwa),
xwa.map_state != IsViewable) {
/* ...if the primary is (or becomes) unviewable or unmapped, it's
probably iconified, and nothing will happen. */
if (XGetWindowAttributes(dpy, topwindow, &xwa),
xwa.map_state != IsViewable)
break;
/* At this stage, we are guaranteed there will be an event of some kind.
Beware; we are presumably in a callback, so this can recurse. */
XtAppNextEvent(cxt, &event);
XtDispatchEvent(&event);
}
#if 0
/* Wait for focus if explicit focus policy */
if (focusPolicy == XmEXPLICIT) {
while(! XmGetFocusWidget(diashell)) {
XtAppNextEvent(cxt, &event);
XtDispatchEvent(&event);
}
}
#endif
}
XmUpdateDisplay(topshell);
}
void ForceWindow(Widget w)
{
Window win;
Display *dpy;
XWindowAttributes xwa;
XEvent event;
XtAppContext cxt;
if (XtIsRealized(w)) {
dpy = XtDisplay(w);
win = XtWindow(w);
cxt = XtWidgetToApplicationContext(w);
/* Wait for the window to be mapped. */
while (XGetWindowAttributes(dpy, win, &xwa),
xwa.map_state != IsViewable) {
XtAppNextEvent(cxt, &event);
XtDispatchEvent(&event);
}
#if 0
/* Wait for focus if explicit focus policy */
if (focusPolicy == XmEXPLICIT) {
while(! XmGetFocusWidget(w)) {
XtAppNextEvent(cxt, &event);
XtDispatchEvent(&event);
}
}
#endif
}
XmUpdateDisplay(w);
}