|
- /*
- ToolsMenu - Add tools to the Workbench Tools menu
-
- Copyright (C) 2015, 2018 Kim Fastrup Larsen
-
- 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 ver-
- sion 3 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be use-
- ful, but WITHOUT ANY WARRANTY; without even the implied war-
- ranty 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 Li-
- cense along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-
- The author can be contacted on <kimflarsen@hotmail.com>
- */
-
- #define INTUI_V36_NAMES_ONLY
-
- #include <dos/dos.h>
- #include <exec/memory.h>
- #include <exec/ports.h>
- #include <intuition/gadgetclass.h>
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <libraries/gadtools.h>
-
- #include <clib/exec_protos.h>
- #include <clib/gadtools_protos.h>
- #include <clib/intuition_protos.h>
-
- #ifdef USE_PRAGMAS
- #include <proto/exec.h>
- #include <proto/gadtools.h>
- #include <proto/intuition.h>
- #endif
-
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <strings.h>
-
- #define CATCOMP_NUMBERS
-
- #include "args.h"
- #include "catalog.h"
- #include "common.h"
- #include "compiler.h"
- #include "cx.h"
- #include "gui.h"
- #include "message.h"
- #include "strings.h"
- #include "wb.h"
-
- #define NOT_SET 0xffffffffU
-
- #define GAD_ID_LIST 1
- #define GAD_ID_NEW 2
- #define GAD_ID_DELETE 3
- #define GAD_ID_NAME 4
- #define GAD_ID_PATH 5
-
- typedef struct {
- int line_h;
- int col1_x;
- int list_y, list_w, list_h, scro_w;
- int gadg_h;
- int name_y, butn_y;
- int col2_x;
- int path_y, path_w;
- int wind_w, wind_h;
- int text_y;
- } Layout;
-
- extern struct IntuitionBase *IntuitionBase;
-
- static struct IntuiText itexts[3] = {
- { 0, 0, JAM1, 0, 0, NULL, NULL, itexts + 1 },
- { 0, 0, JAM1, 0, 0, NULL, NULL, itexts + 2 },
- { 0, 0, JAM1, 0, 0, NULL, NULL, NULL }
- };
- static WORD zoom[4];
-
- static struct MsgPort *user_port;
- static struct Menu *menus;
- static struct Requester busy_req;
- static Message message;
- static Bool message_constructed;
- static struct Screen *screen;
- static struct DrawInfo *draw_info;
- static APTR visual_info;
- static struct Gadget *gadgets;
- static struct Window *window;
- static struct AppWindow *app_window;
-
- static ULONG left_edge;
- static ULONG top_edge = NOT_SET;
-
- static struct Gadget *list_gad, *name_gad, *del_gad, *path_gad;
-
- static Tool *current;
-
- static UBYTE *strgad_buf(struct Gadget *gadget)
- {
- return ((struct StringInfo *) gadget->SpecialInfo)->Buffer;
- }
-
- static void strip_messages_for(struct Window *window)
- {
- struct IntuiMessage *msg, *succ;
-
- msg = (struct IntuiMessage *) window->UserPort->mp_MsgList.lh_Head;
- while ((succ = (struct IntuiMessage *) msg->ExecMessage.mn_Node.ln_Succ)
- != NULL) {
- if (msg->IDCMPWindow == window) {
- Remove(&msg->ExecMessage.mn_Node);
- ReplyMsg(&msg->ExecMessage);
- }
- msg = succ;
- }
- }
-
- static void close_window_safely(struct Window *window)
- {
- Forbid();
- strip_messages_for(window);
- window->UserPort = NULL;
- ModifyIDCMP(window, 0);
- Permit();
- CloseWindow(window);
- }
-
- static Bool set_up_menus(void)
- {
- static struct NewMenu new_menus[] = {
- { NM_TITLE, NULL, NULL, 0, 0, (APTR) MSG_PROJECT_MENU },
- { NM_ITEM, NULL, "S", 0, 0, (APTR) MSG_PROJECT_SAVE },
- { NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL },
- { NM_ITEM, NULL, "H", 0, 0, (APTR) MSG_PROJECT_HIDE },
- { NM_ITEM, NULL, NULL, 0, 0, (APTR) MSG_PROJECT_ABOUT },
- { NM_ITEM, NULL, "Q", 0, 0, (APTR) MSG_PROJECT_QUIT },
- { NM_END, NULL, NULL, 0, 0, NULL }
- };
- struct NewMenu *nm;
-
- for (nm = new_menus; nm->nm_Type != NM_END; ++nm)
- if (nm->nm_UserData != NULL)
- nm->nm_Label = get_string((ULONG) nm->nm_UserData);
- if ((menus = CreateMenus(new_menus, TAG_DONE)) == NULL)
- return NO;
- return YES;
- }
-
- static void render(void)
- {
- PrintIText(window->RPort, itexts, 0, 0);
- }
-
- static void make_layout(Layout *layout)
- {
- int font_w = draw_info->dri_Font->tf_XSize;
- int font_h = draw_info->dri_Font->tf_YSize;
- int pad_x = font_w;
- int pad_y = font_h / 2;
- int lab_h = font_h + 4; /* space taken up by label above a gadget */
- int path_th; /* total height of path gadget and label above */
- int col2_spc; /* vertical spacing around path gadget and text */
-
- layout->line_h = font_h + 1;
- layout->col1_x = pad_x;
- layout->list_y = pad_y + lab_h;
- layout->list_w = 24 * font_w + 12; /* should be divisible by 2 */
- layout->list_h = 6 * layout->line_h + 4;
- layout->scro_w = font_w + 10;
- layout->gadg_h = font_h + 6;
- layout->name_y = layout->list_y + layout->list_h;
- layout->butn_y = layout->name_y + layout->gadg_h;
- layout->col2_x = layout->col1_x + layout->list_w + pad_x;
- layout->path_w = 32 * font_w + 12;
- layout->wind_w = layout->col2_x + layout->path_w + pad_x;
- layout->wind_h = layout->butn_y + layout->gadg_h + pad_y;
- path_th = layout->gadg_h + lab_h;
- col2_spc = (layout->wind_h - path_th - 3 * layout->line_h) / 3;
- layout->path_y = col2_spc + lab_h;
- layout->text_y = 2 * col2_spc + path_th;
- }
-
- static unsigned window_border_top(void)
- {
- return screen->WBorTop + screen->Font->ta_YSize + 1U;
- }
-
- static void make_newgadget(struct NewGadget *ng, WORD left_edge,
- WORD top_edge, WORD width, WORD height, UBYTE *gadget_text, UWORD id,
- ULONG flags)
- {
- ng->ng_LeftEdge = left_edge + screen->WBorLeft;
- ng->ng_TopEdge = top_edge + window_border_top();
- ng->ng_Width = width;
- ng->ng_Height = height;
- ng->ng_GadgetText = gadget_text;
- ng->ng_GadgetID = id;
- ng->ng_Flags = flags;
- }
-
- static Bool create_gadgets(Layout *l)
- {
- struct NewGadget ng;
- struct Gadget *g = CreateContext(&gadgets);
- int butn_w = l->list_w / 2;
-
- ng.ng_TextAttr = screen->Font;
- ng.ng_VisualInfo = visual_info;
- make_newgadget(&ng, l->col1_x, l->list_y, l->list_w, l->list_h,
- get_string(MSG_GAD_MENU_ITEMS), GAD_ID_LIST, 0);
- g = list_gad = CreateGadget(LISTVIEW_KIND, g, &ng,
- GTLV_Labels, tools,
- GTLV_ScrollWidth, (LONG) l->scro_w,
- LAYOUTA_Spacing, 1L,
- TAG_DONE);
- make_newgadget(&ng, l->col1_x, l->name_y, l->list_w, l->gadg_h,
- NULL, GAD_ID_NAME, 0);
- g = name_gad = CreateGadget(STRING_KIND, g, &ng,
- GA_Disabled, (LONG) TRUE,
- TAG_DONE);
- make_newgadget(&ng, l->col1_x, l->butn_y, butn_w, l->gadg_h,
- get_string(MSG_GAD_NEW), GAD_ID_NEW, 0);
- g = CreateGadget(BUTTON_KIND, g, &ng,
- TAG_DONE);
- make_newgadget(&ng, l->col1_x + butn_w, l->butn_y, butn_w, l->gadg_h,
- get_string(MSG_GAD_DELETE), GAD_ID_DELETE, 0);
- g = del_gad = CreateGadget(BUTTON_KIND, g, &ng,
- GA_Disabled, (LONG) TRUE,
- TAG_DONE);
- make_newgadget(&ng, l->col2_x, l->path_y, l->path_w, l->gadg_h,
- get_string(MSG_GAD_TOOL), GAD_ID_PATH, PLACETEXT_ABOVE);
- g = path_gad = CreateGadget(STRING_KIND, g, &ng,
- GTST_MaxChars, (LONG) MAX_PATH_LENGTH,
- GA_Disabled, (LONG) TRUE,
- TAG_DONE);
- return g != NULL;
- }
-
- static void layout_texts(Layout *layout)
- {
- int left_edge = layout->col2_x;
- int top_edge = layout->text_y + window_border_top();
- struct IntuiText *t;
-
- for (t = itexts; t != NULL; t = t->NextText) {
- t->FrontPen = draw_info->dri_Pens[TEXTPEN];
- t->ITextFont = screen->Font;
- t->LeftEdge = left_edge + (layout->path_w - IntuiTextLength(t)) / 2;
- t->TopEdge = top_edge;
- top_edge += layout->line_h;
- }
- }
-
- static Bool open_window(Layout *layout)
- {
- static char window_title_buf[64];
- char *window_title = get_string(MSG_WINDOW_TITLE);
-
- if (strlen(window_title)+strlen(APP_NAME)+strlen(args.cx_popkey) > 64)
- window_title = APP_NAME;
- else {
- sprintf(window_title_buf, window_title, APP_NAME, args.cx_popkey);
- window_title = window_title_buf;
- }
- if ((window = OpenWindowTags(NULL,
- WA_Left, left_edge,
- WA_Top, top_edge,
- WA_InnerWidth, (LONG) layout->wind_w,
- WA_InnerHeight, (LONG) layout->wind_h,
- WA_Flags, (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
- WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH,
- WA_PubScreen, screen,
- WA_Zoom, zoom,
- WA_Gadgets, gadgets,
- WA_Title, window_title,
- WA_AutoAdjust, (LONG) TRUE,
- WA_NewLookMenus, (LONG) TRUE,
- TAG_DONE)) == NULL)
- return NO;
- window->UserPort = user_port;
- ModifyIDCMP(window, IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW
- | LISTVIEWIDCMP | STRINGIDCMP | BUTTONIDCMP);
- GT_RefreshWindow(window, NULL);
- return YES;
- }
-
- static void update_gadgets(void)
- {
- Bool disable = (current == NULL);
-
- GT_SetGadgetAttrs(name_gad, window, NULL,
- GA_Disabled, (LONG) disable,
- GTST_String, disable ? "" : current->node.ln_Name,
- TAG_DONE);
- GT_SetGadgetAttrs(del_gad, window, NULL,
- GA_Disabled, (LONG) disable,
- TAG_DONE);
- GT_SetGadgetAttrs(path_gad, window, NULL,
- GA_Disabled, (LONG) disable,
- GTST_String, disable ? "" : current->path,
- TAG_DONE);
- }
-
- static void update_current(void)
- {
- if (current == NULL)
- return;
- if ((current = cx_modify_tool(current, strgad_buf(name_gad),
- strgad_buf(path_gad))) == NULL)
- update_gadgets();
- }
-
- static void select(int index)
- {
- gui_edit((Tool *) node_at(tools, index));
- }
-
- static void new_tool(void)
- {
- cx_add_tool("", "");
- }
-
- static void delete_tool(void)
- {
- GT_SetGadgetAttrs(name_gad, window, NULL,
- GTST_String, "",
- TAG_DONE);
- update_current();
- }
-
- static void handle_gadgetup(struct Gadget *gadget, UWORD code)
- {
- switch (gadget->GadgetID) {
- case GAD_ID_LIST:
- select(code);
- break;
- case GAD_ID_NEW:
- new_tool();
- break;
- case GAD_ID_DELETE:
- delete_tool();
- break;
- case GAD_ID_NAME:
- case GAD_ID_PATH:
- update_current();
- break;
- }
- }
-
- static void handle_project_menu(UWORD code)
- {
- switch (ITEMNUM(code)) {
- case 0: /* Save Menu Items */
- cx_save_tools();
- break;
- case 2: /* Hide */
- cx_hide();
- break;
- case 3: /* About */
- cx_about();
- break;
- case 4: /* Quit */
- cx_quit();
- break;
- }
- }
-
- static void handle_menupick(UWORD code)
- {
- while (code != MENUNULL) {
- switch (MENUNUM(code)) {
- case 0:
- handle_project_menu(code);
- break;
- }
- code = ItemAddress(menus, code)->NextSelect;
- }
- }
-
- static void handle_closewindow(void)
- {
- cx_hide();
- }
-
- static void handle_refreshwindow(void)
- {
- GT_BeginRefresh(window);
- render();
- GT_EndRefresh(window, TRUE);
- }
-
- static void bring_to_front(void)
- {
- ScreenToFront(window->WScreen);
- WindowToFront(window);
- ActivateWindow(window);
- if (window->Height == zoom[3])
- ZipWindow(window);
- }
-
- static void fill_itexts(struct IntuiText *text, va_list *ap)
- {
- char *s;
-
- while ((s = va_arg(*ap, char *)) != NULL) {
- text->IText = s;
- text->NextText = text + 1;
- ++text;
- }
- (text - 1)->NextText = NULL;
- }
-
- ULONG gui_set_up()
- {
- if (IntuitionBase->LibNode.lib_Version >= 39)
- zoom[0] = zoom[1] = ~0;
- if (!set_up_menus())
- exit(RETURN_FAIL);
- if ((user_port = CreateMsgPort()) == NULL)
- exit(RETURN_FAIL);
- itexts[0].IText = get_string(MSG_INFO_1);
- itexts[1].IText = get_string(MSG_INFO_2);
- itexts[2].IText = get_string(MSG_INFO_3);
- InitRequester(&busy_req);
- if (!message_cons(&message))
- exit(RETURN_FAIL);
- message_constructed = YES;
- return 1UL << user_port->mp_SigBit;
- }
-
- void gui_clean_up()
- {
- if (message_constructed)
- message_dest(&message);
- DeleteMsgPort(user_port);
- if (menus != NULL) /* Really checking if gadtools.library was opened */
- FreeMenus(menus);
- }
-
- void gui_handle_signal()
- {
- struct IntuiMessage *imsg;
- ULONG clas;
- UWORD code;
- APTR iadd;
-
- while ((imsg = GT_GetIMsg(user_port)) != NULL) {
- clas = imsg->Class;
- code = imsg->Code;
- iadd = imsg->IAddress;
- GT_ReplyIMsg(imsg);
- switch (clas) {
- case IDCMP_MENUPICK:
- handle_menupick(code);
- break;
- case IDCMP_CLOSEWINDOW:
- handle_closewindow();
- break;
- case IDCMP_REFRESHWINDOW:
- handle_refreshwindow();
- break;
- case IDCMP_GADGETUP:
- handle_gadgetup(iadd, code);
- break;
- }
- }
- }
-
- void gui_show()
- {
- Layout layout;
-
- if (window != NULL) {
- bring_to_front();
- return;
- }
- if ((screen = LockPubScreen(NULL)) == NULL)
- goto gui_show_failed;
- ScreenToFront(screen);
- if ((draw_info = GetScreenDrawInfo(screen)) == NULL)
- goto gui_show_failed;
- if ((visual_info = GetVisualInfo(screen, TAG_DONE)) == NULL)
- goto gui_show_failed;
- if (!LayoutMenus(menus, visual_info,
- GTMN_NewLookMenus, (LONG) TRUE,
- TAG_DONE))
- goto gui_show_failed;
- if (top_edge == NOT_SET)
- top_edge = screen->BarHeight + 1;
- zoom[2] = 25 * draw_info->dri_Font->tf_XSize;
- zoom[3] = window_border_top();
- make_layout(&layout);
- if (!create_gadgets(&layout))
- goto gui_show_failed;
- layout_texts(&layout);
- if (!open_window(&layout))
- goto gui_show_failed;
- render();
- app_window = wb_add_window(window);
- SetMenuStrip(window, menus);
- current = NULL;
- return;
-
- gui_show_failed:
- gui_hide();
- }
-
- void gui_hide()
- {
- if (app_window != NULL) {
- wb_remove_window(app_window);
- app_window = NULL;
- }
- if (window != NULL) {
- EndRequest(&message.requester, window);
- if (window->MenuStrip != NULL)
- ClearMenuStrip(window);
- left_edge = window->LeftEdge;
- top_edge = window->TopEdge;
- close_window_safely(window);
- window = NULL;
- }
- FreeGadgets(gadgets);
- gadgets = NULL;
- FreeVisualInfo(visual_info);
- visual_info = NULL;
- if (screen != NULL) {
- FreeScreenDrawInfo(screen, draw_info);
- draw_info = NULL;
- UnlockPubScreen(NULL, screen);
- screen = NULL;
- }
- }
-
- void gui_edit(Tool *tool)
- {
- if (window == NULL)
- return;
- current = tool;
- update_gadgets();
- if (current != NULL)
- ActivateGadget(name_gad, window, NULL);
- }
-
- /* Temporarily suspend the listview so we can update the list. */
- void gui_begin_update()
- {
- if (window == NULL)
- return;
- GT_SetGadgetAttrs(list_gad, window, NULL, GTLV_Labels, ~0L, TAG_DONE);
- }
-
- /* Resume normal listview operations. */
- void gui_end_update()
- {
- if (window == NULL)
- return;
- GT_SetGadgetAttrs(list_gad, window, NULL, GTLV_Labels, tools, TAG_DONE);
- }
-
- void gui_begin_busy()
- {
- static UWORD CHIP busy_pointer[] = {
- 0x0000, 0x0000, 0x0400, 0x07c0, 0x0000, 0x07c0, 0x0100, 0x0380,
- 0x0000, 0x07e0, 0x07c0, 0x1ff8, 0x1ff0, 0x3fec, 0x3ff8, 0x7fde,
- 0x3ff8, 0x7fbe, 0x7ffc, 0xff7f, 0x7efc, 0xffff, 0x7ffc, 0xffff,
- 0x3ff8, 0x7ffe, 0x3ff8, 0x7ffe, 0x1ff0, 0x3ffc, 0x07c0, 0x1ff8,
- 0x0000, 0x07e0, 0x0000, 0x0000
- };
-
- if (window == NULL)
- return;
- Request(&busy_req, window);
- if (IntuitionBase->LibNode.lib_Version < 39)
- SetPointer(window, busy_pointer, 16, 16, -6, 0);
- else
- SetWindowPointer(window,
- WA_BusyPointer, (LONG) TRUE,
- WA_PointerDelay, (LONG) TRUE,
- TAG_DONE);
- }
-
- void gui_end_busy()
- {
- if (window == NULL)
- return;
- if (IntuitionBase->LibNode.lib_Version < 39)
- ClearPointer(window);
- else
- SetWindowPointer(window, TAG_DONE);
- EndRequest(&busy_req, window);
- }
-
- void gui_message(char *button_text, ...)
- {
- static struct IntuiText texts[GUI_MESSAGE_MAX_LINES];
- va_list ap;
-
- va_start(ap, button_text);
- if (window == NULL || message.requester.Flags & REQACTIVE)
- goto gui_message_exit;
- fill_itexts(texts, &ap);
- message_layout(&message, window, draw_info, texts, button_text);
- Request(&message.requester, window);
-
- gui_message_exit:
- va_end(ap);
- }
|