Browse Source

Version 1.6

tags/1.6
Carsten Larsen 1 year ago
parent
commit
5f59b3d0da
32 changed files with 3015 additions and 2 deletions
  1. 0
    2
      README.md
  2. 101
    0
      Readme
  3. BIN
      Resources/ToolsMenu.info
  4. 12
    0
      SCOPTIONS
  5. 96
    0
      args.c
  6. 46
    0
      args.h
  7. 135
    0
      broker.c
  8. 32
    0
      broker.h
  9. 67
    0
      catalog.c
  10. 32
    0
      catalog.h
  11. 95
    0
      common.c
  12. 45
    0
      common.h
  13. 28
    0
      compiler.h
  14. 213
    0
      cx.c
  15. 51
    0
      cx.h
  16. 72
    0
      dansk.ct
  17. 51
    0
      error.c
  18. 31
    0
      error.h
  19. 618
    0
      gui.c
  20. 44
    0
      gui.h
  21. 162
    0
      io.c
  22. 31
    0
      io.h
  23. 154
    0
      main.c
  24. 194
    0
      message.c
  25. 43
    0
      message.h
  26. 56
    0
      smakefile
  27. 45
    0
      sprintf.asm
  28. 183
    0
      toolrun.c
  29. 60
    0
      toolrun.h
  30. 71
    0
      toolsmenu.cd
  31. 209
    0
      wb.c
  32. 38
    0
      wb.h

+ 0
- 2
README.md View File

@@ -1,2 +0,0 @@
# ToolsMenu


+ 101
- 0
Readme View File

@@ -0,0 +1,101 @@
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>


New in version 1.6:

- Minor UI adjustments
- New, "proper" requester for About
- Modularized the source code


ToolsMenu is a commodity that will let you add tools to the Tools menu on
your Workbench screen. Once a tool has been added, you can run it by
selecting it from the menu. Any icons selected on the Workbench at that
moment become arguments for the tool.

For example, if you add MultiView, you can then select the icon of an image
on the Workbench, then select MultiView from the menu to view that image.

Tools will be run as if started by the Workbench. You will not be able to
run tools that do not have a proper tool icons.

Adding tools should be pretty self explanatory. Drag tool icons into the
window to add them, after which you can edit their names if you like. You
can also click the "New" button to manually enter a tool. You then write the
name of the tool (as you would like it to appear in the menu) under the
list, and type in the full path of the tool over on the right where it says
"Tool". The path must include the name of the tool's executable file.

When you are happy with your selection of tools, you must remember to save
them from the pull down menu. The definitions will be saved as tool types
in the commodity's icon.

ToolsMenu requires Kickstart 2 or later.

The source code is included in the hope that it will be useful to those out
there who still enjoy programming for the Amiga. Elements of interest
include:

- How to use Catcomp so a project can be localized easily
- How to implement a commodity sporting a GUI
- How to implement a dynamic GUI using Gadtools
- How to read and write tool types
- How to support dragging icons into a window
- How to add items to the Workbench Tools menu
- How to load and run other programs as DOS processes
- How to pretend to be Workbench


History:

1.6 (Nov 26, 2018)

- Minor UI adjustments
- New, "proper" requester for About
- Modularized the source code

1.5 (Jul 28, 2015)

- Busy pointer for Kickstart 2
- Optimized and cleaned up a few things, made code more portable

1.4 (Apr 22, 2015)

- Improved layout for big fonts.
- Added "About..."

1.3 (Feb 12, 2015)

- Fixed an issue that caused some commodities (and possibly other tools) to
crash.

1.2 (Feb 3, 2015)

- Use the user's preferred screen font.

1.1 (Jan 19, 2015)

- Fixed an issue where trying to run a tool with an empty path would cause
a Guru Meditation.

1.0 (Jan 12, 2015)

- Initial release

BIN
Resources/ToolsMenu.info View File


+ 12
- 0
SCOPTIONS View File

@@ -0,0 +1,12 @@
PARAMETERS=REGISTERS
ANSI
SHORTINTEGERS
NOSTACKCHECK
STRINGMERGE
ERRORREXX
OPTIMIZE
OPTIMIZERINLINELOCAL
NOVERSION
MEMORYSIZE=HUGE
DEFINE USE_PRAGMAS
IGNORE=306

+ 96
- 0
args.c View File

@@ -0,0 +1,96 @@
/*
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>
*/

#include <dos/dos.h>
#include <dos/rdargs.h>
#include <workbench/startup.h>

#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

#ifdef USE_PRAGMAS
#include <proto/dos.h>
#include <proto/exec.h>
#endif

#include <stdlib.h>
#include <string.h>

#include "args.h"

#define DEF_CX_PRIORITY 0
#define DEF_CX_POPUP YES
#define DEF_CX_POPKEY "control alt t"

Args args;

static UBYTE **tool_types;
static struct RDArgs *rdargs;

static void get_wb_args(char **argv)
{
struct WBArg *wb_arg = ((struct WBStartup *) argv)->sm_ArgList;

args.exe.dir = wb_arg->wa_Lock;
args.exe.filename = wb_arg->wa_Name;
if ((tool_types = ArgArrayInit(0, argv)) == NULL)
exit(RETURN_FAIL);
args.cx_priority = ArgInt(tool_types, "CX_PRIORITY", DEF_CX_PRIORITY);
args.cx_popup = strcmp(ArgString(tool_types, "CX_POPUP", DEF_CX_POPUP ?
"YES" : "NO"), "NO") != 0;
args.cx_popkey = ArgString(tool_types, "CX_POPKEY", DEF_CX_POPKEY);
}

static void get_shell_args(char **argv)
{
LONG sh_args[3];

args.exe.dir = ((struct Process *) FindTask(NULL))->pr_CurrentDir;
args.exe.filename = argv[0];
sh_args[0] = DEF_CX_PRIORITY;
sh_args[1] = (LONG) DEF_CX_POPKEY;
sh_args[2] = DEF_CX_POPUP ? (LONG) "YES" : (LONG) "NO";
if ((rdargs = ReadArgs(TEMPLATE, sh_args, NULL)) == NULL) {
PrintFault(IoErr(), argv[0]);
exit(RETURN_ERROR);
}
args.cx_priority = sh_args[0];
args.cx_popkey = (STRPTR) sh_args[1];
args.cx_popup = strcmp((char *) sh_args[2], "YES") == 0;
}

void args_set_up(int argc, char **argv)
{
if (argc == 0)
get_wb_args(argv);
else
get_shell_args(argv);
}

void args_clean_up()
{
if (rdargs != NULL)
FreeArgs(rdargs);
if (tool_types != NULL)
ArgArrayDone();
}

+ 46
- 0
args.h View File

@@ -0,0 +1,46 @@
/*
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>
*/

#ifndef ARGS_H
#define ARGS_H

#include <dos/dos.h>
#include <exec/types.h>

#include "common.h"

typedef struct {
struct {
BPTR dir;
char *filename;
} exe;
BYTE cx_priority;
Bool cx_popup;
STRPTR cx_popkey;
} Args;

extern Args args;

void args_set_up(int argc, char **argv);
void args_clean_up(void);

#endif

+ 135
- 0
broker.c View File

@@ -0,0 +1,135 @@
/*
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>
*/

#include <dos/dos.h>
#include <libraries/commodities.h>

#include <clib/commodities_protos.h>
#include <clib/exec_protos.h>

#ifdef USE_PRAGMAS
#include <proto/commodities.h>
#include <proto/exec.h>
#endif

#include <stdlib.h>
#include <strings.h>

#define CATCOMP_NUMBERS

#include "args.h"
#include "broker.h"
#include "catalog.h"
#include "common.h"
#include "cx.h"
#include "error.h"
#include "strings.h"

static struct MsgPort *broker_port;
static CxObj *broker;

ULONG broker_set_up()
{
struct NewBroker new_broker;
LONG error;
CxObj *filter;

if ((broker_port = CreateMsgPort()) == NULL)
exit(RETURN_FAIL);
memset(&new_broker, 0, sizeof new_broker);
new_broker.nb_Version = NB_VERSION;
new_broker.nb_Name = APP_NAME;
new_broker.nb_Title = TITLE;
new_broker.nb_Descr = get_string(MSG_DESCRIPTION);
new_broker.nb_Unique = NBU_UNIQUE | NBU_NOTIFY;
new_broker.nb_Flags = COF_SHOW_HIDE;
new_broker.nb_Pri = args.cx_priority;
new_broker.nb_Port = broker_port;
if ((broker = CxBroker(&new_broker, &error)) == NULL)
exit((error == CBERR_DUP) ? RETURN_OK : RETURN_FAIL);
if ((filter = CxFilter(args.cx_popkey)) == NULL)
exit(RETURN_FAIL);
AttachCxObj(broker, filter);
AttachCxObj(filter, CxSender(broker_port, 0));
AttachCxObj(filter, CxTranslate(NULL));
if ((error = CxObjError(filter)) != 0) {
if (error == COERR_BADFILTER) {
error_message(get_string(MSG_ERR_HOTKEY), NULL);
exit(RETURN_ERROR);
} else
exit(RETURN_FAIL);
}
ActivateCxObj(broker, 1);
return 1UL << broker_port->mp_SigBit;
}

static void handle_command(ULONG msg_id)
{
switch (msg_id) {
case CXCMD_DISABLE:
ActivateCxObj(broker, 0);
cx_disable();
break;
case CXCMD_ENABLE:
ActivateCxObj(broker, 1);
cx_enable();
break;
case CXCMD_KILL:
cx_quit();
break;
case CXCMD_UNIQUE:
case CXCMD_APPEAR:
cx_show();
break;
case CXCMD_DISAPPEAR:
cx_hide();
break;
}
}

void broker_handle_signal()
{
CxMsg *msg;
ULONG msg_type, msg_id;

while ((msg = (CxMsg *) GetMsg(broker_port)) != NULL) {
msg_type = CxMsgType(msg);
msg_id = CxMsgID(msg);
ReplyMsg((struct Message *) msg);
switch (msg_type) {
case CXM_IEVENT:
/* Must be Hot Key event */
cx_show();
break;
case CXM_COMMAND:
handle_command(msg_id);
break;
}
}
}

void broker_clean_up()
{
if (broker != NULL)
DeleteCxObjAll(broker);
delete_port(broker_port);
}

+ 32
- 0
broker.h View File

@@ -0,0 +1,32 @@
/*
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>
*/

#ifndef BROKER_H
#define BROKER_H

#include <exec/types.h>

ULONG broker_set_up(void);
void broker_handle_signal(void);
void broker_clean_up(void);

#endif

+ 67
- 0
catalog.c View File

@@ -0,0 +1,67 @@
/*
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>
*/

#include <exec/types.h>

#include <clib/locale_protos.h>

#ifdef USE_PRAGMAS
#include <proto/locale.h>
#endif

#include "catalog.h"

#define CATCOMP_BLOCK
#include "strings.h"

extern struct Library *LocaleBase;

static APTR catalog;

void open_catalog(STRPTR name)
{
if (LocaleBase != NULL)
catalog = OpenCatalog(NULL, name, TAG_DONE);
}

STRPTR get_string(ULONG id)
{
LONG *l;
UWORD *w;
STRPTR built_in;

l = (LONG *) CatCompBlock;
while (*l != id) {
w = (UWORD *) ((ULONG) l + 4);
l = (LONG *) ((ULONG) l + (ULONG) *w + 6);
}
built_in = (STRPTR) ((ULONG) l + 6);
return (catalog != NULL) ? GetCatalogStr(catalog,id,built_in) : built_in;
}

void close_catalog()
{
if (LocaleBase != NULL) {
CloseCatalog(catalog);
catalog = NULL;
}
}

+ 32
- 0
catalog.h View File

@@ -0,0 +1,32 @@
/*
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>
*/

#ifndef CATALOG_H
#define CATALOG_H

#include <exec/types.h>

void open_catalog(STRPTR catalog);
STRPTR get_string(ULONG id);
void close_catalog(void);

#endif

+ 95
- 0
common.c View File

@@ -0,0 +1,95 @@
/*
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>
*/

#include <exec/lists.h>
#include <exec/memory.h>

#include <clib/exec_protos.h>

#ifdef USE_PRAGMAS
#include <proto/exec.h>
#endif

#include <string.h>

#include "common.h"

char *copy_of(char *s)
{
char *result;

if ((result = AllocVec(strlen(s) + 1, MEMF_PUBLIC)) != NULL)
strcpy(result, s);
return result;
}

void for_all(struct List *l, void (*f)(void *))
{
struct Node *n, *next;

/* This form of iteration allows f() to free nodes */
for (n = l->lh_Head; (next = n->ln_Succ) != NULL; n = next)
(*f)(n);
}

Bool is_in_list(struct List *l, struct Node *node)
{
struct Node *n;

for (n = l->lh_Head; n->ln_Succ != NULL; n = n->ln_Succ)
if (n == node)
return YES;
return NO;
}

struct Node *node_at(struct List *l, int i)
{
struct Node *n;

for (n = l->lh_Head; n->ln_Succ != NULL; n = n->ln_Succ) {
if (i == 0)
return n;
--i;
}
return NULL;
}

int length_of(struct List *l)
{
struct Node *n;
int result = 0;

for (n = l->lh_Head; n->ln_Succ != NULL; n = n->ln_Succ)
++result;
return result;
}

void delete_port(struct MsgPort *port)
{
struct Message *msg;

if (port != NULL) {
while ((msg = GetMsg(port)) != NULL)
ReplyMsg(msg);
DeleteMsgPort(port);
}
}

+ 45
- 0
common.h View File

@@ -0,0 +1,45 @@
/*
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>
*/

#ifndef COMMON_H
#define COMMON_H

#define APP_NAME "ToolsMenu"
#define VERSION "1.6"
#define DATE "26.11.2018"
#define COPYRIGHT "Copyright © 2015, 2018 Kim Fastrup Larsen"
#define TEMPLATE "CX_PRIORITY/N/K,CX_POPKEY/K,CX_POPUP/K"
#define CATALOG "toolsmenu.catalog"
#define TITLE APP_NAME " " VERSION

#define MAX_PATH_LENGTH 127

typedef enum { NO, YES } Bool;

char *copy_of(char *s);
void for_all(struct List *, void (*)(void *));
Bool is_in_list(struct List *, struct Node *);
struct Node *node_at(struct List *, int index);
int length_of(struct List *);
void delete_port(struct MsgPort *);

#endif

+ 28
- 0
compiler.h View File

@@ -0,0 +1,28 @@
/*
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>
*/

#ifndef COMPILER_H
#define COMPILER_H

#define CHIP __chip

#endif

+ 213
- 0
cx.c View File

@@ -0,0 +1,213 @@
/*
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>
*/

#include <dos/dos.h>
#include <exec/memory.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>

#ifdef USE_PRAGMAS
#include <proto/exec.h>
#endif

#include <stdlib.h>

#define CATCOMP_NUMBERS

#include "args.h"
#include "catalog.h"
#include "common.h"
#include "cx.h"
#include "gui.h"
#include "io.h"
#include "strings.h"
#include "wb.h"

struct List *tools;

static Bool enabled = YES;

static void free_tool(Tool *tool)
{
FreeVec(tool->node.ln_Name);
FreeVec(tool->path);
FreeMem(tool, sizeof *tool);
}

static Tool *create_tool(char *name, char *path)
{
Tool *t;

if ((t = AllocMem(sizeof *t, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
return NULL;
if ((t->node.ln_Name = copy_of(name)) == NULL)
goto create_tool_failed;
if ((t->path = copy_of(path)) == NULL)
goto create_tool_failed;
return t;

create_tool_failed:
free_tool(t);
return NULL;
}

static Tool *add_tool(char *name, char *path, struct Node *pred)
{
Tool *tool;

if ((tool = create_tool(name, path)) != NULL) {
Insert(tools, &tool->node, pred);
if (enabled)
wb_add_tool(tool);
}
return tool;
}

static void remove_tool(Tool *tool)
{
if (enabled)
wb_remove_tool(tool);
Remove(&tool->node);
free_tool(tool);
}

static Tool *do_update(Tool *(*f)(Tool *, char *, char *), Tool *tool,
char *name, char *path)
{
Tool *result;

gui_begin_update();
result = (*f)(tool, name, path);
gui_end_update();
return result;
}

static Tool *append(Tool *unused, char *name, char *path)
{
return add_tool(name, path, tools->lh_TailPred);
}

/* Actually creates a new tool and then deletes the old one, to simplify low
memory failure scenarios. If name is blank, it will simply delete the
tool. */
static Tool *modify(Tool *tool, char *name, char *path)
{
Tool *new_tool = NULL;

if (*name != 0 && (new_tool = add_tool(name, path, &tool->node)) == NULL)
return tool;
remove_tool(tool);
return new_tool;

}

static void add_to_menu(void *tool)
{
wb_add_tool((Tool *) tool);
}

static void remove_from_menu(void *tool)
{
wb_remove_tool((Tool *) tool);
}

void cx_set_up()
{
if ((tools = AllocMem(sizeof *tools, MEMF_PUBLIC)) == NULL)
exit(RETURN_FAIL);
NewList(tools);
io_read_definitions(args.exe.dir, args.exe.filename);
}

Tool *cx_add_tool(char *name, char *path)
{
Tool *tool = do_update(append, NULL, name, path);

gui_edit(tool);
return tool;
}

Tool *cx_modify_tool(Tool *tool, char *name, char *path)
{
return do_update(modify, tool, name, path);
}

void cx_enable()
{
if (!enabled) {
enabled = YES;
for_all(tools, add_to_menu);
}
}

void cx_disable()
{
if (enabled) {
enabled = NO;
for_all(tools, remove_from_menu);
}
}

void cx_show()
{
gui_show();
}

void cx_hide()
{
gui_hide();
}

void cx_save_tools()
{
gui_begin_busy();
io_write_definitions(args.exe.dir, args.exe.filename);
gui_end_busy();
}

void cx_about()
{
gui_message(get_string(MSG_GAD_CONTINUE),
TITLE,
COPYRIGHT,
"",
"This program comes with ABSOLUTELY NO WARRANTY.",
"This is free software under the terms of",
"version 3 of the GNU General Public License.",
NULL);
}

void cx_quit()
{
cx_hide();
cx_disable();
exit(RETURN_OK);
}

void cx_clean_up()
{
if (tools != NULL) {
for_all(tools, free_tool);
FreeMem(tools, sizeof *tools);
}
}

+ 51
- 0
cx.h View File

@@ -0,0 +1,51 @@
/*
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>
*/

#ifndef CX_H
#define CX_H

#include <exec/lists.h>

/* We will maintain a list of Tools as the main global state of this
commodity. The name of each Tool (ie. menu item) will be stored in
node.ln_Name. */
typedef struct {
struct Node node;
char *path;
struct AppMenuItem *menu_item;
} Tool;

extern struct List *tools;

void cx_set_up(void);
Tool *cx_add_tool(char *name, char *path);
Tool *cx_modify_tool(Tool *, char *name, char *path);
void cx_enable(void);
void cx_disable(void);
void cx_show(void);
void cx_hide(void);
void cx_save_tools(void);
void cx_about(void);
void cx_quit(void);
void cx_clean_up(void);

#endif

+ 72
- 0
dansk.ct View File

@@ -0,0 +1,72 @@
## version $VER: toolsmenu.catalog 1.6 (26.11.2018)
## codeset 0
## language dansk
;
MSG_ERR_OPEN
Kunne ikke åbne %s
; Could not open %s
;
MSG_ERR_HOTKEY
Ugyldig genvejstast
; Illegal hot key
;
MSG_WINDOW_TITLE
%s: Tryk <%s>
; %s: Hot Key = <%s>
;
MSG_DESCRIPTION
Tilføj værktøjer til Workbench-menuen
; Add tools to the Workbench Tools Menu
;
MSG_PROJECT_MENU
Projekt
; Project
;
MSG_PROJECT_SAVE
Gemme menuposter
; Save Menu Items
;
MSG_PROJECT_HIDE
Gemme væk
; Hide
;
MSG_PROJECT_ABOUT
Omkring...
; About...
;
MSG_PROJECT_QUIT
Afbryde
; Quit
;
MSG_GAD_CONTINUE
Fortsætte
; Continue
;
MSG_GAD_MENU_ITEMS
Menuposter
; Menu Items
;
MSG_GAD_NEW
Ny
; New
;
MSG_GAD_DELETE
Slette
; Delete
;
MSG_GAD_TOOL
Værktøj
; Tool
;
MSG_INFO_1
Værktøjer kan tilføjes
; You can add tools
;
MSG_INFO_2
ved at trække deres ikoner
; by dragging their icons
;
MSG_INFO_3
ind i dette vindue.
; into this window.
;

+ 51
- 0
error.c View File

@@ -0,0 +1,51 @@
/*
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>
*/

#include <intuition/intuition.h>

#include <clib/intuition_protos.h>

#ifdef USE_PRAGMAS
#include <proto/intuition.h>
#endif

#define CATCOMP_NUMBERS

#include "catalog.h"
#include "common.h"
#include "error.h"
#include "strings.h"

extern struct IntuitionBase *IntuitionBase;

void error_message(char *fmt, char *arg)
{
static struct EasyStruct easy_struct = {
sizeof(struct EasyStruct), 0, APP_NAME
};

if (IntuitionBase == NULL)
return;
easy_struct.es_TextFormat = fmt;
easy_struct.es_GadgetFormat = get_string(MSG_GAD_CONTINUE);
EasyRequestArgs(NULL, &easy_struct, NULL, &arg);
}

+ 31
- 0
error.h View File

@@ -0,0 +1,31 @@
/*
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>
*/

#ifndef ERROR_H
#define ERROR_H

/* fmt can contain up to one %s.
If fmt contains a %s, arg must be non-NULL.
*/
void error_message(char *fmt, char *arg);

#endif

+ 618
- 0
gui.c View File

@@ -0,0 +1,618 @@
/*
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);
}

+ 44
- 0
gui.h View File

@@ -0,0 +1,44 @@
/*
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>
*/

#ifndef GUI_H
#define GUI_H

#include <exec/types.h>

#include "cx.h"

#define GUI_MESSAGE_MAX_LINES 6

ULONG gui_set_up(void);
void gui_clean_up(void);
void gui_handle_signal(void);
void gui_show(void);
void gui_hide(void);
void gui_edit(Tool *);
void gui_begin_update(void);
void gui_end_update(void);
void gui_begin_busy(void);
void gui_end_busy(void);
void gui_message(char *button_text, ...);

#endif

+ 162
- 0
io.c View File

@@ -0,0 +1,162 @@
/*
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>
*/

#include <exec/memory.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/icon_protos.h>

#ifdef USE_PRAGMAS
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/icon.h>
#endif

#include <string.h>

#include "common.h"
#include "cx.h"
#include "io.h"

#define DEF_BEGIN '\xab' /* Left double angle quote */
#define DEF_END '\xbb' /* Right double angle quote */

typedef void Disk_object_f(struct DiskObject *, char *);

static void with_disk_object(Disk_object_f *f, BPTR dir, char *filename)
{
BPTR old_dir = CurrentDir(dir);
struct DiskObject *disk_obj = GetDiskObject(filename);

if (disk_obj != NULL) {
(*f)(disk_obj, filename);
FreeDiskObject(disk_obj);
}
CurrentDir(old_dir);
}

static void read_definitions(struct DiskObject *disk_obj, char *filename)
{
char **tt, *def_end;

for (tt = disk_obj->do_ToolTypes; *tt != NULL; ++tt)
/* Identify the tool types that are menu item definitions and create
menu items from them. */
if (**tt == DEF_BEGIN && (def_end = strchr(*tt, DEF_END)) != NULL &&
*(def_end + 1) == ' ') {
/* Temporarily insert terminator to facilitate string copy. */
*def_end = '\0';
cx_add_tool(*tt + 1, def_end + 2);
/* Restore original char to leave string "untouched". */
*def_end = DEF_END;
}
}

/* Count the number of tool types that are not menu item definitions. */
static int non_defs(char **tt)
{
int result = 0;

for ( ; *tt != NULL; ++tt)
if (**tt != DEF_BEGIN)
++result;
return result;
}

/* Create a tool type for a menu item definition. */
static char *create_def(Tool *t)
{
char *def;
size_t name_len = strlen(t->node.ln_Name);

/* Allocate space for name, path, two delimiters, a space, and
string terminator */
def = AllocVec(name_len + strlen(t->path) + 4, 0);
if (def != NULL) {
def[0] = DEF_BEGIN;
strcpy(def + 1, t->node.ln_Name);
def[name_len + 1] = DEF_END;
def[name_len + 2] = ' ';
strcpy(def + name_len + 3, t->path);
}
return def;
}

/* Create a tool type for every menu item in the tools list. */
static Bool create_defs(char **tt)
{
struct Node *n;

for (n = tools->lh_Head; n->ln_Succ != NULL; n = n->ln_Succ)
if ((*(tt++) = create_def((Tool *) n)) == NULL)
return NO;
return YES;
}

/* Copy over those tool types that are not menu item definitions. */
static void copy_non_defs(char **new_tt, char **old_tt)
{
for ( ; *old_tt != NULL; ++old_tt)
if (**old_tt != DEF_BEGIN)
*(new_tt++) = *old_tt;
}

static void free_tool_types(char **tt)
{
char **i;

for (i = tt ; *i != NULL; ++i)
if (**i == DEF_BEGIN)
FreeVec(*i);
FreeVec(tt);
}

static void write_definitions(struct DiskObject *disk_obj, char *filename)
{
int tools_size = length_of(tools);
char **old_tool_types = disk_obj->do_ToolTypes;
int size = tools_size + non_defs(old_tool_types) + 1;
char **new_tool_types = AllocVec(sizeof(char *) * size, MEMF_CLEAR);

if (new_tool_types == NULL)
return;
if (!create_defs(new_tool_types))
goto write_definitions_exit;
copy_non_defs(new_tool_types + tools_size, old_tool_types);
disk_obj->do_ToolTypes = new_tool_types;
PutDiskObject(filename, disk_obj);
disk_obj->do_ToolTypes = old_tool_types;

write_definitions_exit:
free_tool_types(new_tool_types);
}

void io_read_definitions(BPTR dir, char *filename)
{
with_disk_object(read_definitions, dir, filename);
}

void io_write_definitions(BPTR dir, char *filename)
{
with_disk_object(write_definitions, dir, filename);
}

+ 31
- 0
io.h View File

@@ -0,0 +1,31 @@
/*
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>
*/

#ifndef IO_H
#define IO_H

#include <dos/dos.h>

void io_read_definitions(BPTR dir, char *filename);
void io_write_definitions(BPTR dir, char *filename);

#endif

+ 154
- 0
main.c View File

@@ -0,0 +1,154 @@
/*
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>
*/

#include <exec/libraries.h>

#include <clib/exec_protos.h>

#ifdef USE_PRAGMAS
#include <proto/exec.h>
#endif

#include <stdlib.h>

#define CATCOMP_NUMBERS

#include "args.h"
#include "broker.h"
#include "catalog.h"
#include "error.h"
#include "gui.h"
#include "strings.h"
#include "toolrun.h"
#include "wb.h"

#define OS_REQUIRED 37

extern struct Library *SysBase;
extern struct Library *DOSBase;

char *version = "\0$VER: " TITLE " (" DATE ")";

struct Library *CxBase;
struct Library *GadToolsBase;
struct Library *IconBase;
struct Library *IntuitionBase;
struct Library *LocaleBase;
struct Library *WorkbenchBase;

static ULONG signals = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F;
static ULONG wb_signal, tr_signal, broker_signal, gui_signal;

static void check_system_version(void)
{
if (SysBase->lib_Version<OS_REQUIRED||DOSBase->lib_Version<OS_REQUIRED)
exit(RETURN_FAIL);
}

static struct Library *open_library(STRPTR name)
{
struct Library *base;

if ((base = OpenLibrary(name, OS_REQUIRED)) == NULL) {
error_message(get_string(MSG_ERR_OPEN), name);
exit(RETURN_FAIL);
}
return base;
}

static void open_libraries(void)
{
IntuitionBase = open_library("intuition.library");
IconBase = open_library("icon.library");
CxBase = open_library("commodities.library");
GadToolsBase = open_library("gadtools.library");
WorkbenchBase = open_library("workbench.library");
}

static void set_up(int argc, char **argv)
{
LocaleBase = OpenLibrary("locale.library", 38);
open_catalog(CATALOG);
open_libraries();
args_set_up(argc, argv);
signals |= wb_signal = wb_set_up();
signals |= tr_signal = tr_set_up();
signals |= broker_signal = broker_set_up();
signals |= gui_signal = gui_set_up();
cx_set_up();
}

static void main_loop(void)
{
ULONG received;

for (;;) {
received = Wait(signals);
if (received & wb_signal)
wb_handle_signal();
if (received & tr_signal)
tr_handle_signal();
if (received & broker_signal)
broker_handle_signal();
if (received & gui_signal)
gui_handle_signal();
if (received & SIGBREAKF_CTRL_C)
cx_quit();
if (received & SIGBREAKF_CTRL_F)
cx_show();
}
}

static void close_libraries(void)
{
CloseLibrary(WorkbenchBase);
CloseLibrary(GadToolsBase);
CloseLibrary(CxBase);
CloseLibrary(IconBase);
CloseLibrary(IntuitionBase);
}

/* Clean up as much as possible, then wait for the all tools started by us to
quit before finishing up. */
static void clean_up(void)
{
cx_clean_up();
gui_clean_up();
broker_clean_up();
/* tr_clean_up() won't return until all tools have quit. */
tr_clean_up();
wb_clean_up();
args_clean_up();
close_libraries();
close_catalog();
CloseLibrary(LocaleBase);
}

int main(int argc, char **argv)
{
check_system_version();
atexit(clean_up);
set_up(argc, argv);
if (args.cx_popup)
cx_show();
main_loop();
}

+ 194
- 0
message.c View File

@@ -0,0 +1,194 @@
/*
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 <intuition/imageclass.h>
#include <intuition/intuition.h>