diff --git a/requesters/Makefile b/requesters/Makefile new file mode 100644 index 0000000..63e0796 --- /dev/null +++ b/requesters/Makefile @@ -0,0 +1,12 @@ +#CC=vc +aos68k +CC=vc +kick13 +CFLAGS=-c99 -I$(NDK_INC) -DDEBUG + +all: main + +clean: + rm -f *.o main + +main: main.o filereq.o + $(CC) $(CFLAGS) $^ -lamiga -lauto -o $@ + diff --git a/requesters/README.md b/requesters/README.md new file mode 100644 index 0000000..3231623 --- /dev/null +++ b/requesters/README.md @@ -0,0 +1,6 @@ +# Requesters + +## Description + +a project to design standard requesters that will work under any +Amiga operating system version diff --git a/requesters/filereq.c b/requesters/filereq.c new file mode 100644 index 0000000..74815eb --- /dev/null +++ b/requesters/filereq.c @@ -0,0 +1,131 @@ +#include +#include +#include + +#include + +#include "filereq.h" + +#define REQ_TEXT_XOFFSET 10 +#define REQ_WIDTH 240 +#define REQ_HEIGHT 170 +#define TOPAZ_BASELINE 8 + +#define BUTTON_Y 140 +#define BUTTON_HEIGHT 18 + +#define BUTTON_TEXT_XOFFSET 14 +#define OK_BUTTON_X 20 +#define CANCEL_BUTTON_X 160 +#define OK_BUTTON_WIDTH 40 +#define CANCEL_BUTTON_WIDTH 60 + +#define STR_GADGET_X 90 +#define STR_GADGET_Y 120 +#define PATH_GADGET_WIDTH 100 + + +struct Requester requester; +struct IntuiText labels[] = { + {1, 0, JAM2, REQ_TEXT_XOFFSET, STR_GADGET_Y, NULL, "Enter file path", NULL}, + {1, 0, JAM2, 10, TOPAZ_BASELINE - 4, NULL, "Ok", NULL}, + {1, 0, JAM2, 10, TOPAZ_BASELINE - 4, NULL, "Cancel", NULL} /* TOPAZ_BASELINE is 8 */ +}; +WORD gadget_border_points[3][10] = { + {0, 0, OK_BUTTON_WIDTH, 0, OK_BUTTON_WIDTH, BUTTON_HEIGHT, 0, BUTTON_HEIGHT, 0, 0}, + {0, 0, CANCEL_BUTTON_WIDTH, 0, CANCEL_BUTTON_WIDTH, BUTTON_HEIGHT, 0, BUTTON_HEIGHT, 0, 0}, + /* the -2 is the margin to set to avoid that the string gadget will overdraw the + borders */ + {-2, -2, PATH_GADGET_WIDTH, -2, PATH_GADGET_WIDTH, 10, -2, 10, -2, -2} +}; +struct Border gadget_borders[] = { + {0, 0, 1, 0, JAM1, 5, gadget_border_points[0], NULL}, + {0, 0, 1, 0, JAM1, 5, gadget_border_points[1], NULL}, + {0, 0, 1, 0, JAM1, 5, gadget_border_points[2], NULL} +}; + +WORD req_border_points[] = { + 0, 0, REQ_WIDTH - 1, 0, REQ_WIDTH - 1, REQ_HEIGHT - 1, 0, REQ_HEIGHT - 1, 0, 0 +}; +struct Border req_border = {0, 0, 1, 0, JAM1, 5, req_border_points, NULL}; + +UBYTE buffer[81], undobuffer[81]; +struct StringInfo strinfo = {buffer, undobuffer, 0, 80, 0, 0, 0, 0, 0, 0, NULL, 0, NULL}; + +/* + Note: Cancel does not specify the GACT_ENDGADGET flag, it seems that + IDCMP_REQCLEAR is not fired when Intuition closes the requester automatically +*/ +struct Gadget gadgets[] = { + {&gadgets[1], OK_BUTTON_X, BUTTON_Y, OK_BUTTON_WIDTH, BUTTON_HEIGHT, GFLG_GADGHCOMP, + GACT_RELVERIFY, GTYP_BOOLGADGET | GTYP_REQGADGET, &gadget_borders[0], NULL, + &labels[1], 0, NULL, REQ_OK_BUTTON_ID, NULL}, + {&gadgets[2], CANCEL_BUTTON_X, BUTTON_Y, CANCEL_BUTTON_WIDTH, BUTTON_HEIGHT, GFLG_GADGHCOMP, + GACT_RELVERIFY, GTYP_BOOLGADGET | GTYP_REQGADGET, &gadget_borders[1], NULL, + &labels[2], 0, NULL, REQ_CANCEL_BUTTON_ID, NULL}, + {NULL, STR_GADGET_X, STR_GADGET_Y, PATH_GADGET_WIDTH, 10, + GFLG_GADGHCOMP, GACT_RELVERIFY, GTYP_STRGADGET, &gadget_borders[2], NULL, + &labels[3], 0, &strinfo, 103, NULL}, +}; + +BOOL initialized = 0; +#define PATHBUFFER_SIZE 200 +char dirname[PATHBUFFER_SIZE + 1]; +BPTR flock; +LONG error; +struct FileInfoBlock fileinfo; + +void print_fileinfo(struct FileInfoBlock *fileinfo) +{ + if (fileinfo->fib_DirEntryType > 0) { + printf("dir: '%s'\n", fileinfo->fib_FileName); + } else { + printf("file: '%s'\n", fileinfo->fib_FileName); + } +} + +struct Requester *open_file(struct Window *window) +{ + BOOL result; + if (!initialized) { + InitRequester(&requester); + requester.LeftEdge = 20; + requester.TopEdge = 20; + requester.Width = REQ_WIDTH; + requester.Height = REQ_HEIGHT; + requester.Flags = 0; + requester.BackFill = 0; + requester.ReqGadget = &gadgets[0]; + requester.ReqBorder = &req_border; + requester.ReqText = &labels[0]; + + /* scan current directory */ + /* + on AmigaOS versions before 36 (essentially all 1.x versions), the + function GetCurrentDirName() does not exist, but it's obtainable + by calling Cli() and querying the returned CommandLineInterface + structure + */ + puts("scanning directory..."); + /* + // on AmigaOS 1.x, this function does not exist !!! + GetCurrentDirName(dirname, PATHBUFFER_SIZE); + printf("current dir: '%s'\n", dirname); + flock = Lock(dirname, SHARED_LOCK); + if (Examine(flock, &fileinfo)) { + while (ExNext(flock, &fileinfo)) { + print_fileinfo(&fileinfo); + } + error = IoErr(); + if (error != ERROR_NO_MORE_ENTRIES) { + puts("unknown I/O error, TODO handle"); + } + } + UnLock(flock); + */ + + initialized = 1; + } + result = Request(&requester, window); + return result ? &requester : NULL; +} diff --git a/requesters/filereq.h b/requesters/filereq.h new file mode 100644 index 0000000..8e7a28e --- /dev/null +++ b/requesters/filereq.h @@ -0,0 +1,10 @@ +#pragma once +#ifndef __FILEREQ_H__ +#define __FILEREQ_H__ + +extern struct Requester *open_file(struct Window *window); + +#define REQ_OK_BUTTON_ID 101 +#define REQ_CANCEL_BUTTON_ID 102 + +#endif /* __FILEREQ_H__ */ diff --git a/requesters/main b/requesters/main new file mode 100755 index 0000000..fe9fcf7 Binary files /dev/null and b/requesters/main differ diff --git a/requesters/main.c b/requesters/main.c new file mode 100644 index 0000000..e3c4ea9 --- /dev/null +++ b/requesters/main.c @@ -0,0 +1,189 @@ +/* main.c - requester demo application + + This file is part of amiga-stuff. + + amiga-stuff 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 3 of the License, or + (at your option) any later version. + + amiga-stuff 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 amiga30yrs. If not, see . + */ +#include + +#include +#include + +#include +#include +#include +#include + +#ifdef __VBCC__ +#include +#endif +#include "filereq.h" + +#define WIN_LEFT 10 +#define WIN_TOP 10 +#define WIN_WIDTH 340 +#define WIN_HEIGHT 220 +#define WIN_TITLE "IFF Viewer" +#define WIN_MIN_WIDTH 10 +#define WIN_MIN_HEIGHT 10 +#define WIN_MAX_WIDTH WIN_WIDTH +#define WIN_MAX_HEIGHT WIN_HEIGHT + +#define FILE_MENU_NUM 0 +#define NUM_FILE_MENU_ITEMS 2 + +#define OPEN_MENU_ITEM_NUM 0 +#define QUIT_MENU_ITEM_NUM 1 + +struct NewWindow newwin = { + WIN_LEFT, WIN_TOP, WIN_WIDTH, WIN_HEIGHT, 0, 1, + IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_REQCLEAR, + WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH, + NULL, NULL, WIN_TITLE, + NULL, NULL, + WIN_MIN_WIDTH, WIN_MIN_HEIGHT, + WIN_MAX_WIDTH, WIN_MAX_HEIGHT, + WBENCHSCREEN +}; + +struct IntuiText menutext[] = { + {0, 1, JAM2, 0, 1, NULL, "Open...", NULL}, + {0, 1, JAM2, 0, 1, NULL, "Quit", NULL} +}; + +struct MenuItem fileMenuItems[] = { + {&fileMenuItems[1], 0, 0, 0, 0, ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0, + &menutext[0], NULL, 'O', NULL, 0}, + {NULL, 0, 0, 0, 0, ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0, + &menutext[1], NULL, 'Q', NULL, 0} +}; + +struct Menu menus[] = { + {NULL, 20, 0, 0, 0, MENUENABLED | MIDRAWN, "File", &fileMenuItems[0], 0, 0, 0, 0} +}; + +struct Window *window; + +void cleanup() +{ + if (window) { + ClearMenuStrip(window); + CloseWindow(window); + } +} + +struct Requester *filereq; + +BOOL handle_menu(UWORD menuNum, UWORD itemNum, UWORD subItemNum) +{ + printf("menu, menu num: %d, item num: %d, sub item num: %d\n", + (int) menuNum, (int) itemNum, (int) subItemNum); + if (menuNum == FILE_MENU_NUM && itemNum == QUIT_MENU_ITEM_NUM) { + /* quit */ + return TRUE; + } + if (menuNum == FILE_MENU_NUM && itemNum == OPEN_MENU_ITEM_NUM) { + filereq = open_file(window); + } + return FALSE; +} + +void handle_events() +{ + BOOL done = FALSE; + struct IntuiMessage *msg; + ULONG msgClass; + UWORD menuCode; + int buttonId; + + while (!done) { + Wait(1 << window->UserPort->mp_SigBit); + if (msg = (struct IntuiMessage *) GetMsg(window->UserPort)) { + msgClass = msg->Class; + switch (msgClass) { + case IDCMP_CLOSEWINDOW: + done = TRUE; + break; + case IDCMP_MENUPICK: + menuCode = msg->Code; + done = handle_menu(MENUNUM(menuCode), ITEMNUM(menuCode), SUBNUM(menuCode)); + break; + case IDCMP_GADGETUP: + buttonId = (int) ((struct Gadget *) (msg->IAddress))->GadgetID; + if (buttonId == REQ_OK_BUTTON_ID && filereq) EndRequest(filereq, window); + else if (buttonId == REQ_CANCEL_BUTTON_ID && filereq) EndRequest(filereq, window); + break; + case IDCMP_REQCLEAR: + puts("requester closed"); + break; + default: + break; + } + ReplyMsg((struct Message *) msg); + } + } +} + +void setup_menu() +{ + UWORD txWidth, txHeight, txBaseline, txSpacing, itemWidth, itemHeight, numItems; + struct RastPort *rp = &window->WScreen->RastPort; + int i; + + txWidth = rp->TxWidth; + txHeight = rp->TxHeight; + txBaseline = rp->TxBaseline; + txSpacing = rp->TxSpacing; + printf("TxWidth: %d, TxHeight: %d, TxBaseline: %d, TxSpacing: %d\n", + (int) txWidth, (int) txHeight, (int) txBaseline, (int) txSpacing); + + /* Set file menu bounds */ + menus[0].Width = TextLength(rp, "File", strlen("File")) + txWidth; + menus[0].Height = txHeight; + + /* Set file menu items bounds */ + /* We actually need to know what the command uses up */ + itemWidth = txWidth * strlen("Open...") + 50; + itemHeight = txHeight + 2; /* 2 pixels adjustment */ + + numItems = sizeof(fileMenuItems) / sizeof(struct MenuItem); + printf("# file items: %d\n", (int) numItems); + for (i = 0; i < numItems; i++) { + fileMenuItems[i].TopEdge = i * itemHeight; + fileMenuItems[i].Height = itemHeight; + fileMenuItems[i].Width = itemWidth; + } + + SetMenuStrip(window, &menus[0]); +} + +/* Defined automatically in VBCC */ +extern struct Library *DOSBase; + +int main(int argc, char **argv) +{ + /* version: e.g. 34, revision e.g. 3 for Kickstart 1.3 */ + printf("DOS, version: %d, revision: %d\n", + (int) DOSBase->lib_Version, (int) DOSBase->lib_Revision); + + /* Adjust the new screen according to the IFF image */ + if (window = OpenWindow(&newwin)) { + setup_menu(); + // Note: rastport is the entire window, including title bars + //DrawImage(window->RPort, &image, 2, 10); + handle_events(); + } + cleanup(); + return 1; +}