home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Amiga Shareware Floppies
/
ma64.dms
/
ma64.adf
/
FTPMount-1.0
/
Source
/
request.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-10
|
38KB
|
1,624 lines
/*
* This source file is Copyright 1995 by Evan Scott.
* All rights reserved.
* Permission is granted to distribute this file provided no
* fees beyond distribution costs are levied.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <intuition/intuition.h>
#include <intuition/sghooks.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <libraries/commodities.h>
#include <libraries/gadtools.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/commodities.h>
#include <proto/gadtools.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "evtypes.h"
#include "verify.h"
#include "ftp.h"
#include "site.h"
#include "globals.h"
#include "strings.h"
#include "request.h"
#define V_IntuiText 18798
#define V_Gadget 18273
#define V_rastport 1001
#define V_bitmap 1008
struct RastPort *make_rastport(b32 width, b32 height, b32 depth, struct GfxBase *GfxBase)
{
struct RastPort *rp;
struct BitMap *bm;
int i;
b8 *z;
rp = (struct RastPort *)allocate_flags(sizeof(*rp), MEMF_PUBLIC | MEMF_CLEAR, V_rastport);
if (!rp) return 0;
bm = (struct BitMap *)allocate_flags(sizeof(*bm), MEMF_PUBLIC | MEMF_CLEAR, V_bitmap);
if (bm) {
InitBitMap(bm, depth, width, height);
bm->Planes[0] = AllocRaster(width, height * depth);
if (bm->Planes[0]) {
z = (b8 *)bm->Planes[0];
for (i = 1; i < depth; i++) {
z += bm->BytesPerRow * bm->Rows;
bm->Planes[i] = (void *)z;
}
InitRastPort(rp);
rp->BitMap = bm;
rp->Mask = 0xff;
return rp;
}
deallocate(bm, V_bitmap);
}
deallocate(rp, V_rastport);
return 0;
}
void free_rastport(struct RastPort *rp, struct GfxBase *GfxBase)
{
FreeRaster(rp->BitMap->Planes[0], rp->BitMap->BytesPerRow * 8, rp->BitMap->Rows * rp->BitMap->Depth);
deallocate(rp->BitMap, V_bitmap);
deallocate(rp, V_rastport);
}
struct IntuiText nulltext = {
0, 0,
JAM1,
0, 0,
(void *)0,
"",
(void *)0
};
struct gim *make_gim(b8 *name, b32 textpen, b32 lightpen, b32 darkpen, struct Screen *s,
struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
struct IntuiText txt;
int width, height, owidth, oheight;
struct gim *gim;
sb32 x, y, Rx, Ry, Rx2, Ry2, R2, new_delta, old_delta;
txt.FrontPen = textpen;
txt.BackPen = 0;
txt.DrawMode = JAM2;
txt.LeftEdge = 0;
txt.TopEdge = 0;
txt.ITextFont = s->Font;
txt.IText = name;
txt.NextText = nil;
if (s->Font) height = s->Font->ta_YSize;
else height = 8;
width = IntuiTextLength(&txt);
owidth = width + height;
oheight = 3 * height / 2;
gim = (struct gim *)allocate(sizeof(*gim), V_gim);
if (!gim) return nil;
ensure(gim, V_gim);
gim->rp1 = make_rastport(owidth, oheight, 3, GfxBase);
if (!gim->rp1) {
deallocate(gim, V_gim);
return nil;
}
gim->rp2 = make_rastport(owidth, oheight, 3, GfxBase);
if (!gim->rp2) {
free_rastport(gim->rp1, GfxBase);
deallocate(gim, V_gim);
return nil;
}
gim->im1.LeftEdge = 0;
gim->im1.TopEdge = 0;
gim->im1.Width = owidth;
gim->im1.Height = oheight;
gim->im1.Depth = 3;
gim->im1.ImageData = (void *)gim->rp1->BitMap->Planes[0];
gim->im1.PlanePick = 7;
gim->im1.PlaneOnOff = 0;
gim->im1.NextImage = nil;
gim->im2 = gim->im1;
gim->im2.ImageData = (void *)gim->rp2->BitMap->Planes[0];
SetRast(gim->rp1, 0);
SetRast(gim->rp2, 0);
PrintIText(gim->rp1, &txt, height / 2, height / 4);
PrintIText(gim->rp2, &txt, height / 2 + 1, height / 4 + 1);
Rx = Ry = 2 * height / 3;
Rx2 = Rx * Rx;
Ry2 = Ry * Ry;
R2 = Rx2 * Ry2;
for (x = 0; x < Rx; x++) {
y = 0;
new_delta = abs(R2 - Ry2*x*x - Rx2*y*y);
do {
old_delta = new_delta;
y++;
new_delta = abs(R2 - Ry2*x*x - Rx2*y*y);
} while (old_delta > new_delta);
SetAPen(gim->rp1, lightpen);
WritePixel(gim->rp1, Rx - x, Ry - (y - 1));
WritePixel(gim->rp1, owidth - Rx - 1 + x, Ry - (y - 1));
SetAPen(gim->rp1, darkpen);
WritePixel(gim->rp1, Rx - x, oheight - Ry - 1 + (y - 1));
WritePixel(gim->rp1, owidth - Rx - 1 + x, oheight - Ry - 1 + (y - 1));
SetAPen(gim->rp2, darkpen);
WritePixel(gim->rp2, Rx - x, Ry - (y - 1));
WritePixel(gim->rp2, owidth - Rx - 1 + x, Ry - (y - 1));
SetAPen(gim->rp2, lightpen);
WritePixel(gim->rp2, Rx - x, oheight - Ry - 1 + (y - 1));
WritePixel(gim->rp2, owidth - Rx - 1 + x, oheight - Ry - 1 + (y - 1));
}
for (y = 0; y < Ry; y++) {
x = 0;
new_delta = abs(R2 - Ry2 * x * x - Rx2 * y * y);
do {
old_delta = new_delta;
x++;
new_delta = abs(R2 - Ry2 * x * x - Rx2 * y * y);
} while (old_delta > new_delta);
SetAPen(gim->rp1, lightpen);
WritePixel(gim->rp1, Rx - (x - 1), Ry - y);
WritePixel(gim->rp1, Rx - (x - 1), oheight - Ry - 1 + y);
SetAPen(gim->rp1, darkpen);
WritePixel(gim->rp1, owidth - Rx - 1 + (x - 1), Ry - y);
WritePixel(gim->rp1, owidth - Rx - 1 + (x - 1), oheight - Ry - 1 + y);
SetAPen(gim->rp2, darkpen);
WritePixel(gim->rp2, Rx - (x - 1), Ry - y);
WritePixel(gim->rp2, Rx - (x - 1), oheight - Ry - 1 + y);
SetAPen(gim->rp2, lightpen);
WritePixel(gim->rp2, owidth - Rx - 1 + (x - 1), Ry - y);
WritePixel(gim->rp2, owidth - Rx - 1 + (x - 1), oheight - Ry - 1 + y);
}
SetAPen(gim->rp1, lightpen);
Move(gim->rp1, Rx, 0);
Draw(gim->rp1, owidth - Rx - 1, 0);
Move(gim->rp1, 0, Ry);
Draw(gim->rp1, 0, oheight - Ry - 1);
SetAPen(gim->rp1, darkpen);
Move(gim->rp1, Rx, oheight - 1);
Draw(gim->rp1, owidth - Rx - 1, oheight - 1);
Move(gim->rp1, owidth - 1, Ry);
Draw(gim->rp1, owidth - 1, oheight - Ry - 1);
SetAPen(gim->rp2, darkpen);
Move(gim->rp2, Rx, 0);
Draw(gim->rp2, owidth - Rx - 1, 0);
Move(gim->rp2, 0, Ry);
Draw(gim->rp2, 0, oheight - Ry - 1);
SetAPen(gim->rp2, lightpen);
Move(gim->rp2, Rx, oheight - 1);
Draw(gim->rp2, owidth - Rx - 1, oheight - 1);
Move(gim->rp2, owidth - 1, Ry);
Draw(gim->rp2, owidth - 1, oheight - Ry - 1);
return gim;
}
void free_gim(struct gim *gim, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
verify(gim, V_gim);
free_rastport(gim->rp1, GfxBase);
free_rastport(gim->rp2, GfxBase);
deallocate(gim, V_gim);
return;
}
struct Gadget *make_gadget(struct gim *gim)
{
struct Gadget *g;
if (!gim) return nil;
verify(gim, V_gim);
g = (struct Gadget *)allocate(sizeof(*g), V_Gadget);
if (!g) return nil;
g->NextGadget = nil;
g->LeftEdge = 0;
g->TopEdge = 0;
g->Width = gim->im1.Width;
g->Height = gim->im1.Height;
g->Flags = GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
g->Activation = GACT_RELVERIFY;
g->GadgetType = GTYP_BOOLGADGET;
g->GadgetRender = &gim->im1;
g->SelectRender = &gim->im2;
g->GadgetText = &nulltext;
g->MutualExclude = 0;
g->SpecialInfo = nil;
g->GadgetID = 0;
g->UserData = nil;
return g;
}
void free_gadget(struct Gadget *g)
{
deallocate(g, V_Gadget);
}
struct Window *connect_req(site *sp, b8 *s)
{
struct Window *w;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *pub_screen;
b32 screen_modeID;
struct Rectangle rect;
struct Gadget *cancel;
struct IntuiText txt;
int width, swidth, sheight, fheight;
b8 *z;
verify(sp, V_site);
GfxBase = sp->GBase;
IntuitionBase = sp->IBase;
pub_screen = LockPubScreen(nil);
if (pub_screen) {
screen_modeID = GetVPModeID(&pub_screen->ViewPort);
if (screen_modeID != INVALID_ID) {
if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT)) {
cancel = make_gadget(cancel_gim);
if (cancel) {
z = (b8 *)allocate(strlen(s) + 19, V_cstr);
if (z) {
strcpy(z, strings[MSG_CONNECTING_TO]);
strcat(z, s);
strcat(z, " ...");
txt.FrontPen = 1;
txt.BackPen = 0;
txt.DrawMode = JAM1;
txt.LeftEdge = 0;
txt.TopEdge = 0;
txt.ITextFont = pub_screen->Font;
txt.IText = z;
txt.NextText = nil;
if (pub_screen->Font) fheight = pub_screen->Font->ta_YSize;
else fheight = 8;
width = IntuiTextLength(&txt) * 4 / 3;
txt.LeftEdge = width / 8;
txt.TopEdge = fheight / 2;
swidth = rect.MaxX - rect.MinX + 1;
sheight = rect.MaxY - rect.MinY + 1;
if (pub_screen->TopEdge > 0)
sheight -= pub_screen->TopEdge;
if (sheight > pub_screen->Height) sheight = pub_screen->Height;
if (swidth > pub_screen->Width) swidth = pub_screen->Width;
if (sheight < fheight * 6) sheight = fheight * 6;
if (swidth < width) swidth = width;
w = OpenWindowTags(nil,
WA_Left, swidth / 2 - pub_screen->LeftEdge - width / 2,
WA_Top, sheight / 2 - pub_screen->TopEdge - fheight * 3,
WA_Width, width,
WA_Height, fheight * 6,
WA_Flags, WFLG_DEPTHGADGET | WFLG_DRAGBAR |
WFLG_SMART_REFRESH |
WFLG_NOCAREREFRESH,
WA_IDCMP, IDCMP_GADGETUP,
WA_PubScreen, pub_screen,
WA_Title, strings[MSG_CONNECTING],
TAG_END, 0
);
if (w) {
UnlockPubScreen(nil, pub_screen);
PrintIText(w->RPort, &txt, 0, w->BorderTop);
deallocate(z, V_cstr);
w->UserData = (void *)cancel;
cancel->LeftEdge = w->Width - w->BorderRight - fheight / 2 - cancel->Width;
cancel->TopEdge = w->Height - w->BorderBottom - fheight / 3 - cancel->Height;
AddGadget(w, cancel, (b32)0);
RefreshGList(cancel, w, nil, 1);
return w;
}
deallocate(z, V_cstr);
}
free_gadget(cancel);
}
}
}
UnlockPubScreen(nil, pub_screen);
}
return nil;
}
void close_req(site *sp, struct Window *w)
{
struct Gadget *cancel;
struct Message *msg;
struct IntuitionBase *IntuitionBase;
verify(sp, V_site);
IntuitionBase = sp->IBase;
Forbid();
while (msg = GetMsg(w->UserPort)) ReplyMsg(msg);
cancel = (struct Gadget *)w->UserData;
RemoveGadget(w, cancel);
free_gadget(cancel);
CloseWindow(w);
Permit();
}
struct phdata {
b8 password[MAX_PASS_LENGTH + 1];
b8 undo[MAX_PASS_LENGTH + 1];
};
boolean __saveds __asm password_hook(register __a0 struct Hook *hook,
register __a1 b32 *msg,
register __a2 struct SGWork *sgw)
{
struct phdata *phd;
phd = hook->h_Data;
if (*msg == SGH_KEY) {
switch (sgw->EditOp) {
case EO_REPLACECHAR:
case EO_INSERTCHAR:
phd->password[sgw->BufferPos - 1] = sgw->WorkBuffer[sgw->BufferPos - 1];
sgw->WorkBuffer[sgw->BufferPos - 1] = '*';
break;
case EO_MOVECURSOR:
sgw->Actions &=~ SGA_USE;
sgw->Actions |= SGA_BEEP;
break;
case EO_RESET:
strcpy(phd->password, phd->undo);
break;
}
if (sgw->BufferPos != sgw->NumChars) {
sgw->BufferPos = sgw->NumChars;
sgw->Actions |= SGA_REDISPLAY;
}
phd->password[sgw->NumChars] = 0;
return true;
} else if (*msg == SGH_CLICK) {
sgw->BufferPos = sgw->NumChars;
sgw->Actions |= SGA_REDISPLAY;
return true;
} else {
return false;
}
}
boolean user_pass_request(site *sp, struct Window *canw)
/*
* open a requester asking for username and password, filled in as appropriate
* Inputs:
* sp : site pointer
* canw : cancel window (will still be open in the background, and may be used)
*
* Result:
* false if cancel is selected in either canw or the requester, or a major failure occurred
* true if login is selected, or return is pressed in password field
*/
{
struct Gadget *glist, *gad, *login, *cancel, *userg, *passg;
struct NewGadget user, pass;
struct Screen *s;
void *vi;
b32 screen_modeID;
struct Rectangle rect;
struct Window *w;
sb32 swidth, sheight, fheight, wheight;
b32 signals, csig;
struct IntuiMessage *im;
struct Hook pass_hook;
b8 *z;
struct phdata phd;
struct IntuitionBase *IntuitionBase;
struct Library *GadToolsBase;
struct GfxBase *GfxBase;
verify(sp, V_site);
IntuitionBase = sp->IBase;
GfxBase = sp->GBase;
GadToolsBase = sp->GTBase;
glist = nil;
pass_hook.h_Entry = (b32 (*)())password_hook;
pass_hook.h_SubEntry = (b32 (*)())nil;
pass_hook.h_Data = (void *)&phd;
s = LockPubScreen(nil);
if (!s) return false;
ScreenToFront(s);
if (s->Font) fheight = s->Font->ta_YSize;
else fheight = 8;
if (sp->password) {
strcpy(phd.password, sp->password);
strcpy(phd.undo, sp->password);
z = sp->password;
while (*z) {
*z++ = '*';
}
} else {
phd.password[0] = 0;
phd.undo[0] = 0;
}
wheight = fheight * 8;
vi = GetVisualInfo(s, TAG_END);
if (vi != nil) {
screen_modeID = GetVPModeID(&s->ViewPort);
if (screen_modeID != INVALID_ID) {
if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT)) {
swidth = rect.MaxX - rect.MinX + 1;
sheight = rect.MaxY - rect.MinY + 1;
sprintf(sp->read_buffer, strings[MSG_LOGIN_TO], sp->host);
w = OpenWindowTags(nil,
WA_Left, swidth / 4 - s->LeftEdge,
WA_Top, sheight / 2 - wheight / 2 - s->TopEdge,
WA_Width, swidth / 2,
WA_Height, wheight,
WA_IDCMP, IDCMP_ACTIVEWINDOW | IDCMP_REFRESHWINDOW |
BUTTONIDCMP | STRINGIDCMP,
WA_PubScreen, s,
WA_Activate, true,
WA_DragBar, true,
WA_DepthGadget, true,
WA_Title, sp->read_buffer,
WA_AutoAdjust, true,
TAG_END
);
if (w) {
gad = CreateContext(&glist);
if (gad) {
user.ng_LeftEdge = w->Width / 4;
user.ng_TopEdge = w->BorderTop + fheight / 2;
user.ng_Width = (w->Width * 3 / 4) - w->BorderRight - fheight / 2;
user.ng_Height = fheight * 3 / 2;
user.ng_GadgetText = strings[MSG_USER_NAME];
user.ng_TextAttr = s->Font;
user.ng_GadgetID = 1;
user.ng_Flags = PLACETEXT_LEFT;
user.ng_VisualInfo = vi;
pass.ng_LeftEdge = w->Width / 4;
pass.ng_TopEdge = w->BorderTop + (fheight * 5 / 2);
pass.ng_Width = (w->Width * 3 / 4) - w->BorderRight - fheight / 2;
pass.ng_Height = fheight * 3 / 2;
pass.ng_GadgetText = strings[MSG_PASSWORD_NAME];
pass.ng_TextAttr = s->Font;
pass.ng_GadgetID = 2;
pass.ng_Flags = PLACETEXT_LEFT;
pass.ng_VisualInfo = vi;
userg = gad = CreateGadget(STRING_KIND, gad, &user,
GTST_String, sp->user,
GTST_MaxChars, MAX_USER_LENGTH,
TAG_END
);
passg = gad = CreateGadget(STRING_KIND, gad, &pass,
GTST_String, sp->password,
GTST_MaxChars, MAX_PASS_LENGTH,
GTST_EditHook, (b32)&pass_hook,
TAG_END
);
if (gad) {
login = make_gadget(login_gim);
if (login) {
cancel = make_gadget(cancel_gim);
if (cancel) {
login->LeftEdge = fheight / 2 + w->BorderLeft;
login->TopEdge = w->Height - w->BorderBottom - login->Height - fheight / 2;
cancel->LeftEdge = w->Width - w->BorderRight - cancel->Width - fheight / 2;
cancel->TopEdge = login->TopEdge;
login->GadgetID = 3;
cancel->GadgetID = 4;
AddGadget(w, cancel, 100);
AddGadget(w, login, 100);
AddGList(w, glist, 0, 100, nil);
RefreshGadgets(glist, w, nil);
GT_RefreshWindow(w, nil);
goto listen;
}
free_gadget(login);
}
}
FreeGadgets(glist);
}
CloseWindow(w);
}
}
}
FreeVisualInfo(vi);
}
UnlockPubScreen(nil, s);
return false;
listen:
csig = 1 << canw->UserPort->mp_SigBit | sp->abort_signals | sp->disconnect_signals;
signals = (1 << w->UserPort->mp_SigBit) | csig;
while (1) {
if (Wait(signals) & csig) {
CloseWindow(w);
FreeGadgets(glist);
free_gadget(cancel);
free_gadget(login);
FreeVisualInfo(vi);
UnlockPubScreen(nil, s);
return false;
}
while (im = GT_GetIMsg(w->UserPort)) {
gad = (struct Gadget *)im->IAddress;
switch (im->Class) {
case IDCMP_ACTIVEWINDOW:
if (sp->needs_user) {
ActivateGadget(userg, w, nil);
} else {
ActivateGadget(passg, w, nil);
}
break;
case IDCMP_GADGETUP:
switch (gad->GadgetID) {
case 1:
if (im->Code == 0) {
ActivateGadget(passg, w, nil);
}
sp->needs_user = false;
break;
case 2:
if (im->Code != 0) {
break;
}
/* else fall through to Login */
case 3:
if (sp->user) deallocate(sp->user, V_cstr);
if (sp->password) deallocate(sp->password, V_cstr);
z = ((struct StringInfo *)userg->SpecialInfo)->Buffer;
if (z[0] != '\0') {
sp->user = (b8 *)allocate(strlen(z) + 1, V_cstr);
if (sp->user) {
strcpy(sp->user, z);
}
} else {
sp->user = nil;
}
z = phd.password;
if (z[0] != '\0') {
sp->password = (b8 *)allocate(strlen(z) + 1, V_cstr);
if (sp->password) {
strcpy(sp->password, z);
}
} else {
sp->password = nil;
}
Forbid();
GT_ReplyIMsg(im);
CloseWindow(w);
Permit();
FreeGadgets(glist);
free_gadget(cancel);
free_gadget(login);
FreeVisualInfo(vi);
UnlockPubScreen(nil, s);
return true;
case 4:
Forbid();
GT_ReplyIMsg(im);
CloseWindow(w);
Permit();
FreeGadgets(glist);
free_gadget(cancel);
free_gadget(login);
FreeVisualInfo(vi);
UnlockPubScreen(nil, s);
return false;
}
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(w);
GT_EndRefresh(w, true);
break;
}
GT_ReplyIMsg(im);
}
}
}
struct Window *open_main_window(struct List *site_labels, struct IntuitionBase *IntuitionBase, struct Library *GadToolsBase, struct GfxBase *GfxBase)
{
struct Gadget *glist, *gad;
struct NewGadget ng;
struct Screen *s;
void *vi;
b32 screen_modeID;
struct Rectangle rect;
struct Window *w;
sb32 swidth, sheight;
glist = nil;
s = LockPubScreen(nil);
if (!s) return nil;
vi = GetVisualInfo(s, TAG_END);
if (vi != nil) {
screen_modeID = GetVPModeID(&s->ViewPort);
if (screen_modeID != INVALID_ID) {
if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT)) {
swidth = rect.MaxX - rect.MinX + 1;
sheight = rect.MaxY - rect.MinY + 1;
w = OpenWindowTags(nil,
WA_Left, swidth / 3 - s->LeftEdge,
WA_Top, sheight / 4 - s->TopEdge,
WA_Width, swidth / 3,
WA_Height, sheight / 2,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | LISTVIEWIDCMP,
WA_PubScreen, s,
WA_Activate, true,
WA_DragBar, true,
WA_DepthGadget, true,
WA_CloseGadget, true,
WA_Title, strings[MSG_CURRENT_SITES],
WA_AutoAdjust, true,
TAG_END
);
if (w) {
gad = CreateContext(&glist);
if (gad) {
ng.ng_TextAttr = s->Font;
ng.ng_VisualInfo = vi;
ng.ng_LeftEdge = w->BorderLeft;
ng.ng_TopEdge = w->BorderTop;
ng.ng_Width = w->Width - w->BorderLeft - w->BorderRight;
ng.ng_Height = w->Height - w->BorderTop - w->BorderBottom;
ng.ng_GadgetText = nil;
ng.ng_GadgetID = 0;
ng.ng_Flags = 0;
gad = CreateGadget(LISTVIEW_KIND, gad, &ng,
GTLV_ReadOnly, false,
GTLV_Labels, site_labels,
TAG_END
);
if (gad) {
AddGList(w, glist, 0, -1, nil);
RefreshGadgets(glist, w, nil);
GT_RefreshWindow(w, nil);
w->UserData = (void *)glist;
FreeVisualInfo(vi);
UnlockPubScreen(nil, s);
return w;
}
FreeGadgets(glist);
}
CloseWindow(w);
}
}
}
FreeVisualInfo(vi);
}
UnlockPubScreen(nil, s);
return nil;
}
void close_main_window(struct Window *w, struct IntuitionBase *IntuitionBase, struct Library *GadToolsBase)
{
struct Gadget *glist;
struct IntuiMessage *im;
Forbid();
while (im = GT_GetIMsg(w->UserPort)) {
if (im->Class == IDCMP_REFRESHWINDOW) {
GT_BeginRefresh(w);
GT_EndRefresh(w, true);
}
GT_ReplyIMsg(im);
}
glist = (struct Gadget *)w->UserData;
CloseWindow(w);
FreeGadgets(glist);
Permit();
}
#define V_List 19561
#define V_Node 20079
struct List *site_list(void)
{
struct List *l;
struct Node *n;
site *sp;
l = (struct List *)allocate(sizeof(*l), V_List);
if (!l) return l;
NewList(l);
Forbid();
sp = sites;
while (sp) {
n = (struct Node *)allocate(sizeof(*n), V_Node);
if (!n) {
Permit();
return l;
}
n->ln_Name = (b8 *)allocate(strlen(sp->name) + 1, V_cstr);
if (!n->ln_Name) {
Permit();
deallocate(n, V_Node);
return l;
}
strcpy(n->ln_Name, sp->name);
n->ln_Pri = 0;
AddTail(l, n);
sp = sp->next;
}
Permit();
return l;
}
void free_labels(struct List *l)
{
struct Node *n;
while (n = RemHead(l)) {
deallocate(n->ln_Name, V_cstr);
deallocate(n, V_Node);
}
deallocate(l, V_List);
}
void draw_fill_bar(site *sp, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
struct Window *w;
struct RastPort *rp;
b32 x1, y1, x2, y2, gap;
verify(sp, V_site);
w = sp->status_window;
if (!w) return;
rp = w->RPort;
x1 = w->BorderLeft;
y1 = w->BorderTop;
x2 = w->Width - w->BorderRight - 1;
y2 = sp->abort_gadget->TopEdge - 1;
gap = (y2 - y1) / 4;
x2 = x1 + (x2 - x1) * 3 / 4;
x1 += gap;
y1 += gap;
y2 -= gap;
SetDrMd(rp, JAM2);
SetAPen(rp, lightpen);
Move(rp, x2, y1);
Draw(rp, x2, y2);
Draw(rp, x1, y2);
SetAPen(rp, darkpen);
Draw(rp, x1, y1);
Draw(rp, x2, y1);
SetAPen(rp, fillpen);
x1++;
y1++;
y2--;
x2--;
if (sp->file_list) {
verify(sp->file_list, V_file_info);
x2 = x1 + ((x2 - x1) * sp->file_list->rpos) / sp->file_list->end;
RectFill(rp, x1, y1, x2, y2);
}
}
void update_fill_bar(site *sp, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
struct Window *w;
struct RastPort *rp;
b32 x1, y1, x2, y2, gap;
struct IntuiText txt;
b8 buffer[20], *z;
file_info *fip;
verify(sp, V_site);
w = sp->status_window;
if (!w) return;
Forbid();
fip = sp->file_list;
if (!fip) {
Permit();
return;
}
verify(fip, V_file_info);
z = fip->fname + strlen(fip->fname) - 1;
while (z > fip->fname && *z != '/') z--;
if (*z == '/') z++;
rp = w->RPort;
x1 = w->BorderLeft;
y1 = w->BorderTop;
x2 = w->Width - w->BorderRight - 1;
y2 = sp->abort_gadget->TopEdge - 1;
gap = (y2 - y1) / 4;
x2 = x1 + (x2 - x1) * 3 / 4 - 1;
x1 += gap + 1;
y1 += gap + 1;
y2 -= gap + 1;
if (sp->site_state == SS_WRITING || !fip->end) { /* just print how many k we have transferred */
txt.FrontPen = textpen;
txt.BackPen = 0;
txt.DrawMode = JAM2;
txt.LeftEdge = x1;
txt.TopEdge = y1;
txt.ITextFont = sp->status_window->WScreen->Font;
txt.NextText = nil;
txt.IText = z;
PrintIText(rp, &txt, 0, 0);
txt.LeftEdge += IntuiTextLength(&txt);
txt.FrontPen = textpen;
txt.IText = buffer;
buffer[0] = ':';
buffer[1] = ' ';
x1 = 2;
y1 = fip->rpos / 1024;
buffer[x1] = '0';
while (y1 >= 100000) {
buffer[x1]++;
y1 -= 100000;
}
if (buffer[x1] > '0') x1++;
buffer[x1] = '0';
while (y1 >= 10000) {
buffer[x1]++;
y1 -= 10000;
}
if (buffer[x1] > '0' || x1 != 2) x1++;
buffer[x1] = '0';
while (y1 >= 1000) {
buffer[x1]++;
y1 -= 1000;
}
if (buffer[x1] > '0' || x1 != 2) x1++;
buffer[x1] = '0';
while (y1 >= 100) {
buffer[x1]++;
y1 -= 100;
}
if (buffer[x1] > '0' || x1 != 2) x1++;
buffer[x1] = '0';
while (y1 >= 10) {
buffer[x1]++;
y1 -= 10;
}
if (buffer[x1] > '0' || x1 != 2) x1++;
buffer[x1++] = y1 + '0';
buffer[x1++] = ' ';
buffer[x1++] = 'k';
buffer[x1++] = ' ';
buffer[x1++] = ' ';
buffer[x1] = 0;
PrintIText(rp, &txt, 0, 0);
Permit();
return;
}
/* reading ... can do a filler bar */
SetDrMd(rp, JAM2);
SetAPen(rp, fillpen);
txt.FrontPen = lightpen;
txt.BackPen = 0;
txt.DrawMode = JAM1;
txt.TopEdge = y1;
txt.ITextFont = sp->status_window->WScreen->Font;
txt.NextText = nil;
txt.IText = z;
txt.LeftEdge = (x1 + x2) / 2 - IntuiTextLength(&txt) / 2;
x2 = x1 + ((x2 - x1) * sp->file_list->rpos) / sp->file_list->end;
RectFill(rp, x1, y1, x2, y2);
PrintIText(rp, &txt, 0, 0);
Permit();
return;
}
void draw_state(site *sp, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
struct IntuiText txt;
/* gadget states */
switch (sp->site_state) {
case SS_DISCONNECTED:
case SS_DISCONNECTING:
if (!(sp->abort_gadget->Flags & GFLG_DISABLED)) {
OffGadget(sp->abort_gadget, sp->status_window, nil);
}
if (!(sp->disconnect_gadget->Flags & GFLG_DISABLED)) {
OffGadget(sp->disconnect_gadget, sp->status_window, nil);
}
break;
case SS_CONNECTING:
case SS_IDLE:
case SS_LOGIN:
case SS_ABORTING:
if (!(sp->abort_gadget->Flags & GFLG_DISABLED)) {
OffGadget(sp->abort_gadget, sp->status_window, nil);
}
if (sp->disconnect_gadget->Flags & GFLG_DISABLED) {
OnGadget(sp->disconnect_gadget, sp->status_window, nil);
}
break;
default:
if (sp->abort_gadget->Flags & GFLG_DISABLED) {
OnGadget(sp->abort_gadget, sp->status_window, nil);
}
if (sp->disconnect_gadget->Flags & GFLG_DISABLED) {
OnGadget(sp->disconnect_gadget, sp->status_window, nil);
}
break;
}
txt.FrontPen = textpen;
txt.BackPen = 0;
txt.DrawMode = JAM2;
txt.LeftEdge = 2;
txt.TopEdge = 0;
txt.ITextFont = sp->status_window->WScreen->Font;
txt.NextText = nil;
txt.IText = strings[MSG_STATE_UNKNOWN + sp->site_state];
PrintIText(sp->status_window->RPort, &txt, sp->status_window->BorderLeft,
sp->abort_gadget->TopEdge + sp->abort_gadget->Height / 4);
if (sp->quick) {
txt.LeftEdge += IntuiTextLength(&txt);
txt.IText = strings[MSG_QUICK_FLAG];
PrintIText(sp->status_window->RPort, &txt, sp->status_window->BorderLeft,
sp->abort_gadget->TopEdge + sp->abort_gadget->Height / 4);
}
if (sp->site_state == SS_READING && sp->file_list && sp->file_list->end > 0) {
draw_fill_bar(sp, IntuitionBase, GfxBase);
}
}
void clear_state(site *sp, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
verify(sp, V_site);
truth(sp->status_window != nil);
SetAPen(sp->status_window->RPort, 0);
SetDrMd(sp->status_window->RPort, JAM1);
RectFill(sp->status_window->RPort, sp->status_window->BorderLeft, sp->status_window->BorderTop,
sp->abort_gadget->LeftEdge - 1, sp->status_window->Height - sp->status_window->BorderBottom - 1);
RectFill(sp->status_window->RPort, sp->abort_gadget->LeftEdge, sp->status_window->BorderTop,
sp->status_window->Width - sp->status_window->BorderRight - 1,
sp->abort_gadget->TopEdge - 1);
}
void open_status_window(site *sp, struct MsgPort *wport, struct IntuitionBase *IntuitionBase, struct GfxBase *GfxBase)
{
struct Screen *s;
struct Rectangle rect;
b32 screen_modeID;
struct Gadget *aborg, *disg;
b16 swidth, sheight, fheight;
struct Window *w;
verify(sp, V_site);
if (sp->status_window) {
WindowToFront(sp->status_window);
ActivateWindow(sp->status_window);
return;
}
s = LockPubScreen(nil);
if (!s) return;
if (s->Font) fheight = s->Font->ta_YSize;
else fheight = 8;
screen_modeID = GetVPModeID(&s->ViewPort);
if (screen_modeID != INVALID_ID) {
if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT)) {
aborg = make_gadget(abort_gim);
if (aborg) {
aborg->GadgetID = 1;
disg = make_gadget(disconnect_gim);
if (disg) {
disg->GadgetID = 2;
swidth = rect.MaxX - rect.MinX + 1;
sheight = rect.MaxY - rect.MinY + 1;
w = OpenWindowTags(nil,
WA_Left, swidth / 4 - s->LeftEdge,
WA_Top, sheight / 3 - s->TopEdge,
WA_Width, swidth / 2,
WA_Height, fheight * 4 + disg->Height,
WA_Flags, WFLG_DEPTHGADGET | WFLG_DRAGBAR |
WFLG_SMART_REFRESH |
WFLG_CLOSEGADGET |
WFLG_NOCAREREFRESH,
WA_IDCMP, 0,
WA_PubScreen, s,
WA_Title, sp->name,
TAG_END, 0
);
if (w) {
UnlockPubScreen(nil, s);
w->UserPort = wport;
ModifyIDCMP(w, IDCMP_CLOSEWINDOW | IDCMP_GADGETUP);
aborg->NextGadget = disg;
disg->NextGadget = nil;
sp->abort_gadget = aborg;
sp->disconnect_gadget = disg;
disg->LeftEdge = w->Width - w->BorderRight - disg->Width - fheight / 2;
disg->TopEdge = w->Height - w->BorderBottom - disg->Height - fheight / 3;
aborg->TopEdge = disg->TopEdge;
aborg->LeftEdge = disg->LeftEdge - aborg->Width - fheight / 2;
AddGList(w, aborg, (b32)-1, 2, nil);
RefreshGadgets(aborg, w, nil);
sp->status_window = w;
w->UserData = (void *)sp;
draw_state(sp, IntuitionBase, GfxBase);
return;
}
free_gadget(disg);
}
free_gadget(aborg);
}
}
}
UnlockPubScreen(nil, s);
return;
}
void close_status_window(site *sp, struct MsgPort *wport, struct IntuitionBase *IntuitionBase)
{
struct IntuiMessage *im;
struct Node *succ;
struct Window *w;
verify(sp, V_site);
w = sp->status_window;
if (!w) return;
Forbid();
im = (struct IntuiMessage *)wport->mp_MsgList.lh_Head;
while (succ = im->ExecMessage.mn_Node.ln_Succ) {
if (im->IDCMPWindow == w) {
Remove((struct Node *)im);
ReplyMsg((struct Message *)im);
}
im = (struct IntuiMessage *)succ;
}
w->UserPort = nil;
ModifyIDCMP(w, 0);
Permit();
CloseWindow(w);
free_gadget(sp->abort_gadget);
free_gadget(sp->disconnect_gadget);
sp->status_window = nil;
return;
}
void __saveds status_handler(void)
{
struct Process *me;
struct MsgPort *rank, *sync, *myport, *cxport, *winport;
status_message *reserve, *startup, *sm;
struct Library *GadToolsBase, *CxBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
CxObj *broker, *filter, *sender, *translate;
CxMsg *cxmsg;
b32 signals;
b32 msgid, msgtype;
struct Window *mainw;
struct NewBroker nb;
struct List *site_labels;
struct IntuiMessage *imsg;
struct Node *n;
site *sp;
mainw = nil;
site_labels = nil;
me = (struct Process *)FindTask(0l);
myport = &me->pr_MsgPort;
WaitPort(myport);
startup = (status_message *)GetMsg(myport);
mem_tracking_on();
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
if (IntuitionBase) {
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 36);
if (GfxBase) {
GadToolsBase = OpenLibrary("gadtools.library", 0);
if (GadToolsBase) {
CxBase = OpenLibrary("commodities.library", 0);
if (CxBase) {
rank = CreatePort(0, 0);
if (rank) {
sync = CreatePort(0, 0);
if (sync) {
cxport = CreatePort(0, 0);
if (cxport) {
winport = CreatePort(0, 0);
if (winport) {
reserve = (status_message *)allocate_flags(sizeof(*reserve), MEMF_PUBLIC, V_status_message);
if (reserve) {
ensure(reserve, V_status_message);
reserve->header.mn_Length = sizeof(*reserve);
reserve->header.mn_ReplyPort = sync;
reserve->header.mn_Node.ln_Name = "ftpstatus reserve message";
reserve->header.mn_Node.ln_Type = NT_MESSAGE;
reserve->header.mn_Node.ln_Pri = 0;
nb.nb_Version = NB_VERSION;
nb.nb_Name = strings[MSG_BROKER_NAME];
nb.nb_Title = "FTPMount v" VERSION "." REVISION;
nb.nb_Descr = strings[MSG_BROKER_DESCR];
nb.nb_Unique = NBU_DUPLICATE;
nb.nb_Flags = COF_SHOW_HIDE;
nb.nb_Pri = 0;
nb.nb_Port = cxport;
nb.nb_ReservedChannel = 0;
broker = CxBroker(&nb, nil);
if (broker) {
/* this hotkey stuff taken directly from RKM example */
if (filter = CxFilter(strings[MSG_HOTKEY])) {
/* if we can't add the hotkey stuff, don't fail */
if (sender = CxSender(cxport, 1)) {
if (translate = (CxTranslate(nil))) {
AttachCxObj(broker, filter);
AttachCxObj(filter, sender);
AttachCxObj(filter, translate);
}
}
}
ActivateCxObj(broker, 1l);
startup->command = 0;
ReplyMsg(&startup->header);
goto begin_listening;
}
deallocate(reserve, V_status_message);
}
DeletePort(winport);
}
DeletePort(cxport);
}
DeletePort(sync);
}
DeletePort(rank);
}
CloseLibrary(CxBase);
}
CloseLibrary(GadToolsBase);
}
CloseLibrary((struct Library *)GfxBase);
}
CloseLibrary((struct Library *)IntuitionBase);
}
startup->command = SM_KILL;
Forbid();
ReplyMsg(&startup->header);
return;
begin_listening:
signals = (1 << myport->mp_SigBit) | (1 << cxport->mp_SigBit) | (1 << winport->mp_SigBit);
while (1) {
Wait(signals);
while (cxmsg = (CxMsg *)GetMsg(cxport)) {
msgid = CxMsgID(cxmsg);
msgtype = CxMsgType(cxmsg);
ReplyMsg((struct Message *)cxmsg);
switch (msgtype) {
case CXM_IEVENT: /* copied from CXCMD_APPEAR below */
if (mainw != nil) {
close_main_window(mainw, IntuitionBase, GadToolsBase);
mainw = nil;
free_labels(site_labels);
}
site_labels = site_list();
mainw = open_main_window(site_labels, IntuitionBase, GadToolsBase, GfxBase);
signals = (1 << cxport->mp_SigBit) |
(1 << myport->mp_SigBit) |
(1 << winport->mp_SigBit);
if (mainw != nil) {
signals |= (1 << mainw->UserPort->mp_SigBit);
}
break;
case CXM_COMMAND:
switch (msgid) {
case CXCMD_DISABLE:
reserve->command = SM_SUSPEND;
PutMsg(status_control, &reserve->header);
WaitPort(sync); GetMsg(sync);
ActivateCxObj(broker, 0l);
break;
case CXCMD_ENABLE:
reserve->command = SM_RESUME;
PutMsg(status_control, &reserve->header);
WaitPort(sync); GetMsg(sync);
ActivateCxObj(broker, 1l);
break;
case CXCMD_KILL:
reserve->command = SM_KILL;
PutMsg(status_control, &reserve->header);
WaitPort(sync); GetMsg(sync);
break;
case CXCMD_APPEAR:
if (mainw != nil) {
close_main_window(mainw, IntuitionBase, GadToolsBase);
mainw = nil;
free_labels(site_labels);
}
site_labels = site_list();
mainw = open_main_window(site_labels, IntuitionBase, GadToolsBase, GfxBase);
signals = (1 << cxport->mp_SigBit) |
(1 << myport->mp_SigBit) |
(1 << winport->mp_SigBit);
if (mainw != nil) {
signals |= (1 << mainw->UserPort->mp_SigBit);
}
break;
case CXCMD_DISAPPEAR:
if (mainw != nil) {
close_main_window(mainw, IntuitionBase, GadToolsBase);
mainw = nil;
free_labels(site_labels);
signals = (1 << cxport->mp_SigBit) |
(1 << myport->mp_SigBit) |
(1 << winport->mp_SigBit);
}
break;
}
}
}
while (mainw && (imsg = GT_GetIMsg(mainw->UserPort))) {
switch (imsg->Class) {
case IDCMP_CLOSEWINDOW:
GT_ReplyIMsg(imsg);
close_main_window(mainw, IntuitionBase, GadToolsBase);
mainw = nil;
free_labels(site_labels);
signals = (1 << cxport->mp_SigBit) |
(1 << myport->mp_SigBit) |
(1 << winport->mp_SigBit);
continue;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(mainw);
GT_EndRefresh(mainw, true);
break;
case IDCMP_GADGETUP:
msgid = imsg->Code;
GT_ReplyIMsg(imsg);
close_main_window(mainw, IntuitionBase, GadToolsBase);
mainw = nil;
n = site_labels->lh_Head;
while (msgid-- && (n->ln_Succ)) {
n = n->ln_Succ;
}
if (n->ln_Succ) {
sp = sites;
while (sp) {
if (strcmp(sp->name, n->ln_Name) == 0) {
break;
}
sp = sp->next;
}
if (sp) {
open_status_window(sp, winport, IntuitionBase, GfxBase);
}
}
free_labels(site_labels);
signals = (1 << cxport->mp_SigBit) |
(1 << myport->mp_SigBit) |
(1 << winport->mp_SigBit);
continue;
default:
break;
}
GT_ReplyIMsg(imsg);
}
while (imsg = (struct IntuiMessage *)GetMsg(winport)) {
sp = (site *)imsg->IDCMPWindow->UserData;
verify(sp, V_site);
switch (imsg->Class) {
case IDCMP_CLOSEWINDOW:
ReplyMsg((struct Message *)imsg);
close_status_window(sp, winport, IntuitionBase);
continue;
case IDCMP_GADGETUP:
if (((struct Gadget *)imsg->IAddress)->GadgetID == 1) {
/* abort */
Signal(sp->port->mp_SigTask, sp->abort_signals);
} else {
/* disconnect */
Signal(sp->port->mp_SigTask, sp->disconnect_signals);
}
break;
}
ReplyMsg((struct Message *)imsg);
}
while (sm = (status_message *)GetMsg(myport)) {
verify(sm, V_status_message);
switch (sm->command) {
case SM_KILL:
if (mainw != nil) {
close_main_window(mainw, IntuitionBase, GadToolsBase);
free_labels(site_labels);
}
Forbid();
while (cxmsg = (CxMsg *)GetMsg(cxport)) {
ReplyMsg((struct Message *)cxmsg);
}
DeleteCxObjAll(broker);
Permit();
deallocate(reserve, V_status_message);
DeletePort(winport);
DeletePort(cxport);
DeletePort(sync);
DeletePort(rank);
check_memory();
CloseLibrary(CxBase);
CloseLibrary(GadToolsBase);
CloseLibrary((struct Library *)GfxBase);
CloseLibrary((struct Library *)IntuitionBase);
Forbid();
ReplyMsg(&sm->header);
return;
case SM_NEW_SITE:
if (sm->data) {
open_status_window(sm->this_site, winport, IntuitionBase, GfxBase);
}
break;
case SM_DEAD_SITE:
close_status_window(sm->this_site, winport, IntuitionBase);
break;
case SM_STATE_CHANGE:
if (sm->this_site->status_window) {
clear_state(sm->this_site, IntuitionBase, GfxBase);
draw_state(sm->this_site, IntuitionBase, GfxBase);
}
break;
case SM_PROGRESS:
if (sm->this_site->status_window) {
update_fill_bar(sm->this_site, IntuitionBase, GfxBase);
}
break;
}
ReplyMsg(&sm->header);
}
}
}