#include "xmh.h"
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <X11/cursorfont.h>
#include <X11/Xos.h>
#ifndef abs
#define abs(x) ((x) < 0 ? (-(x)) : (x))
#endif
static char *SysErrorMsg (int n)
{
char *s = strerror(n);
return (s ? s : "no such error");
}
void Punt(char *str)
{
(void) fprintf( stderr, "%s: %s\nerrno = %d; %s\007\n",
progName, str, errno, SysErrorMsg(errno) );
if (app_resources.debug) {
(void)fprintf(stderr, "forcing core dump.\n");
(void) fflush(stderr);
abort();
}
else {
(void)fprintf(stderr, "exiting.\n");
(void)fflush(stderr);
_exit(-1);
}
}
int myopen(char *path, int flags, int mode)
{
int fid;
fid = open(path, flags, mode);
if (fid >= 0) DEBUG2("# %d : %s\n", fid, path)
return fid;
}
FILE *myfopen(char *path, char *mode)
{
FILE *result;
result = fopen(path, mode);
if (result) DEBUG2("# %d : %s\n", fileno(result), path)
return result;
}
void myclose(int fid)
{
if (close(fid) < 0) Punt("Error in myclose!");
DEBUG1( "# %d : <Closed>\n", fid)
}
void myfclose(FILE *file)
{
int fid = fileno(file);
if (fclose(file) < 0) Punt("Error in myfclose!");
DEBUG1("# %d : <Closed>\n", fid)
}
char *MakeNewTempFileName(void)
{
static char name[60];
static int uniqueid = 0;
do {
(void) sprintf(name, "%s/xmh_%ld_%d", app_resources.temp_dir,
(long)getpid(), uniqueid++);
} while (FileExists(name));
return name;
}
char **MakeArgv(int n)
{
char **result;
result = ((char **) XtMalloc((unsigned) (n+1) * sizeof(char *)));
result[n] = 0;
return result;
}
char **ResizeArgv(char **argv, int n)
{
argv = ((char **) XtRealloc((char *) argv, (unsigned) (n+1) * sizeof(char *)));
argv[n] = 0;
return argv;
}
FILEPTR FOpenAndCheck(char *name, char *mode)
{
FILEPTR result;
result = myfopen(name, mode);
if (result == NULL) {
char str[500];
perror(progName);
(void)sprintf(str, "Error in FOpenAndCheck(%s, %s)", name, mode);
Punt(str);
}
return result;
}
static char *DoReadLine(FILEPTR fid, char lastchar)
{
static char *buf;
static int maxlength = 0;
char *ptr, c;
int length = 0;
ptr = buf;
c = ' ';
while (c != '\n' && !feof(fid)) {
c = getc(fid);
if (length++ > maxlength - 5) {
if (maxlength)
buf = XtRealloc(buf, (unsigned) (maxlength *= 2));
else
buf = XtMalloc((unsigned) (maxlength = 512));
ptr = buf + length - 1;
}
*ptr++ = c;
}
if (!feof(fid) || length > 1) {
*ptr = 0;
*--ptr = lastchar;
return buf;
}
return NULL;
}
char *ReadLine(FILEPTR fid)
{
return DoReadLine(fid, 0);
}
char *ReadLineWithCR(FILEPTR fid)
{
return DoReadLine(fid, '\n');
}
void DeleteFileAndCheck(char *name)
{
if (strcmp(name, "/dev/null") != 0 && unlink(name) == -1) {
char str[500];
perror(progName);
(void)sprintf(str, "DeleteFileAndCheck(%s) failed!", name);
Punt(str);
}
}
void CopyFileAndCheck(char *from, char *to)
{
int fromfid, tofid, n;
char buf[512];
fromfid = myopen(from, O_RDONLY, 0666);
tofid = myopen(to, O_WRONLY | O_TRUNC | O_CREAT, 0666);
if (fromfid < 0 || tofid < 0) {
perror(progName);
(void)sprintf(buf, "CopyFileAndCheck(%s->%s) failed!", from, to);
Punt(buf);
}
do {
n = read(fromfid, buf, 512);
if (n) (void) write(tofid, buf, n);
} while (n);
myclose(fromfid);
myclose(tofid);
}
void RenameAndCheck(char *from, char *to)
{
if (rename(from, to) == -1) {
if (errno != EXDEV) {
char str[500];
perror(progName);
(void)sprintf(str, "RenameAndCheck(%s->%s) failed!", from, to);
Punt(str);
}
CopyFileAndCheck(from, to);
DeleteFileAndCheck(from);
}
}
char *CreateGeometry(int gbits, int x, int y, int width, int height)
{
char *result, str1[10], str2[10], str3[10], str4[10];
if (gbits & WidthValue)
(void) sprintf(str1, "=%d", width);
else
(void) strcpy(str1, "=");
if (gbits & HeightValue)
(void) sprintf(str2, "x%d", height);
else
(void) strcpy(str2, "x");
if (gbits & XValue)
(void) sprintf(str3, "%c%d", (gbits & XNegative) ? '-' : '+', abs(x));
else
(void) strcpy(str3, "");
if (gbits & YValue)
(void) sprintf(str4, "%c%d", (gbits & YNegative) ? '-' : '+', abs(y));
else
(void) strcpy(str4, "");
result = XtMalloc((unsigned) 22);
(void) sprintf(result, "%s%s%s%s", str1, str2, str3, str4);
return result;
}
int FileExists(char *file)
{
return (access(file, F_OK) == 0);
}
long LastModifyDate(char *file)
{
struct stat buf;
if (stat(file, &buf)) return -1;
return buf.st_mtime;
}
int GetFileLength(char *file)
{
struct stat buf;
if (stat(file, &buf)) return -1;
return buf.st_size;
}
Boolean IsSubfolder(char *foldername)
{
return (strchr(foldername, '/')) ? True : False;
}
void SetCurrentFolderName(Scrn scrn, char *foldername)
{
scrn->curfolder = foldername;
ChangeLabel((Widget) scrn->folderlabel, foldername);
}
void ChangeLabel(Widget widget, char *str)
{
static Arg arglist[] = {{XtNlabel, (XtArgVal)NULL}};
arglist[0].value = (XtArgVal) str;
XtSetValues(widget, arglist, XtNumber(arglist));
}
Widget CreateTextSW(
Scrn scrn,
char *name,
ArgList args,
Cardinal num_args)
{
return XtCreateManagedWidget( name, asciiTextWidgetClass, scrn->widget,
args, num_args);
}
Widget CreateTitleBar(Scrn scrn, char *name)
{
Widget result;
int height;
static Arg arglist[] = {
{XtNlabel, (XtArgVal)NULL},
};
arglist[0].value = (XtArgVal) app_resources.banner;
result = XtCreateManagedWidget( name, labelWidgetClass, scrn->widget,
arglist, XtNumber(arglist) );
height = GetHeight(result);
XawPanedSetMinMax(result, height, height);
return result;
}
void Feep(int type, int volume, Window win)
{
#ifdef XKB
XkbStdBell(theDisplay, win, volume, type);
#else
XBell(theDisplay, volume);
#endif
}
MsgList CurMsgListOrCurMsg(Toc toc)
{
MsgList result;
Msg curmsg;
result = TocCurMsgList(toc);
if (result->nummsgs == 0 && (curmsg = TocGetCurMsg(toc))) {
FreeMsgList(result);
result = MakeSingleMsgList(curmsg);
}
return result;
}
int GetHeight(Widget w)
{
Dimension height;
Arg args[1];
XtSetArg(args[0], XtNheight, &height);
XtGetValues( w, args, (Cardinal)1 );
return (int)height;
}
int GetWidth(Widget w)
{
Dimension width;
Arg args[1];
XtSetArg(args[0], XtNwidth, &width);
XtGetValues( w, args, (Cardinal)1 );
return (int)width;
}
Toc SelectedToc(Scrn scrn)
{
Toc toc;
if ((toc = TocGetNamed(scrn->curfolder)) == NULL)
toc = TocCreate(scrn->curfolder);
return toc;
}
Toc CurrentToc(Scrn scrn)
{
return scrn->toc;
}
int strncmpIgnoringCase(char *str1, char *str2, int length)
{
int i, diff;
for (i=0 ; i<length ; i++, str1++, str2++) {
diff = ((*str1 >= 'A' && *str1 <= 'Z') ? (*str1 + 'a' - 'A') : *str1) -
((*str2 >= 'A' && *str2 <= 'Z') ? (*str2 + 'a' - 'A') : *str2);
if (diff) return diff;
}
return 0;
}
void StoreWindowName(Scrn scrn, char *str)
{
static Arg arglist[] = {
{XtNiconName, (XtArgVal) NULL},
{XtNtitle, (XtArgVal) NULL},
};
arglist[0].value = arglist[1].value = (XtArgVal) str;
XtSetValues(scrn->parent, arglist, XtNumber(arglist));
}
void InitBusyCursor(Scrn scrn)
{
unsigned long valuemask;
XSetWindowAttributes attributes;
if (! app_resources.block_events_on_busy || scrn->wait_window)
return;
valuemask = CWDontPropagate | CWCursor;
attributes.do_not_propagate_mask = (KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask);
attributes.cursor = app_resources.busy_cursor;
scrn->wait_window =
XCreateWindow(XtDisplay(scrn->parent), XtWindow(scrn->parent), 0, 0,
rootwidth, rootheight, (unsigned int) 0, CopyFromParent,
InputOnly, CopyFromParent, valuemask, &attributes);
}
void ShowBusyCursor(void)
{
register int i;
for (i=0; i < numScrns; i++)
if (scrnList[i]->mapped)
XMapWindow(theDisplay, scrnList[i]->wait_window);
}
void UnshowBusyCursor(void)
{
register int i;
for (i=0; i < numScrns; i++)
if (scrnList[i]->mapped)
XUnmapWindow(theDisplay, scrnList[i]->wait_window);
}
void SetCursorColor(
Widget widget,
Cursor cursor,
unsigned long foreground)
{
XColor colors[2];
Arg args[2];
Colormap cmap;
colors[0].pixel = foreground;
XtSetArg(args[0], XtNbackground, &(colors[1].pixel));
XtSetArg(args[1], XtNcolormap, &cmap);
XtGetValues(widget, args, (Cardinal) 2);
XQueryColors(XtDisplay(widget), cmap, colors, 2);
XRecolorCursor(XtDisplay(widget), cursor, &colors[0], &colors[1]);
}