/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); } } }