espelhamento de https://frontier.innolan.net/rainlance/ToolsMenu.git
210 linhas
6.1 KiB
C
Arquivo executável
210 linhas
6.1 KiB
C
Arquivo executável
/*
|
|
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 <workbench/startup.h>
|
|
#include <workbench/workbench.h>
|
|
|
|
#include <clib/dos_protos.h>
|
|
#include <clib/exec_protos.h>
|
|
#include <clib/icon_protos.h>
|
|
#include <clib/wb_protos.h>
|
|
|
|
#ifdef USE_PRAGMAS
|
|
#include <proto/dos.h>
|
|
#include <proto/exec.h>
|
|
#include <proto/icon.h>
|
|
#include <proto/wb.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <strings.h>
|
|
|
|
#include "common.h"
|
|
#include "cx.h"
|
|
#include "toolrun.h"
|
|
#include "wb.h"
|
|
|
|
static struct MsgPort *wb_port;
|
|
|
|
static void add_tool_from_icon(char *name)
|
|
{
|
|
char path[MAX_PATH_LENGTH + 1];
|
|
BPTR lock;
|
|
|
|
if ((lock = Lock(name, ACCESS_READ)) == NULL)
|
|
return;
|
|
if (NameFromLock(lock, path, MAX_PATH_LENGTH + 1))
|
|
cx_add_tool(name, path);
|
|
UnLock(lock);
|
|
}
|
|
|
|
static void handle_app_window_msg(struct AppMessage *msg)
|
|
{
|
|
struct WBArg *arg;
|
|
struct WBArg *end = msg->am_ArgList + msg->am_NumArgs;
|
|
BPTR old_dir;
|
|
struct DiskObject *disk_obj;
|
|
|
|
cx_show();
|
|
for (arg = msg->am_ArgList; arg != end; ++arg) {
|
|
old_dir = CurrentDir(arg->wa_Lock);
|
|
/* Check that name isn't NULL and isn't empty, and that the icon is
|
|
a Workbench tool. */
|
|
if (arg->wa_Name != NULL && *arg->wa_Name != '\0')
|
|
if ((disk_obj = GetDiskObject(arg->wa_Name)) != NULL) {
|
|
if (disk_obj->do_Type == WBTOOL)
|
|
add_tool_from_icon(arg->wa_Name);
|
|
FreeDiskObject(disk_obj);
|
|
}
|
|
CurrentDir(old_dir);
|
|
}
|
|
ReplyMsg((struct Message *) msg);
|
|
}
|
|
|
|
static void free_args(struct WBArg *arg_list, LONG num_args)
|
|
{
|
|
FreeVec(arg_list[0].wa_Name);
|
|
if (arg_list[0].wa_Lock != NULL)
|
|
UnLock(arg_list[0].wa_Lock);
|
|
FreeMem(arg_list, sizeof(struct WBArg) * num_args);
|
|
}
|
|
|
|
/* Creates the directory locks and tool names to pass to tr_run_tool(). It
|
|
actually only creates the first element, ie. the home directory and name
|
|
of the tool itself, the rest are copied from the AppMessage that
|
|
workbench.library sent us. */
|
|
static struct WBArg *create_args(STRPTR path, struct WBArg *arg_list,
|
|
LONG num_args)
|
|
{
|
|
struct WBArg *result;
|
|
size_t args_size;
|
|
UBYTE t;
|
|
UBYTE *file_part;
|
|
|
|
/* Create an array one element bigger than the one received from
|
|
workbench.library, so we can put the tool itself at the front. */
|
|
args_size = sizeof(struct WBArg) * num_args;
|
|
result = AllocMem(args_size+sizeof(struct WBArg),MEMF_PUBLIC|MEMF_CLEAR);
|
|
if (result == NULL)
|
|
return NULL;
|
|
/* Temporarily separate the file part and directory part of the tool's
|
|
path with a string terminator. */
|
|
t = *(file_part = FilePart(path));
|
|
*file_part = '\0';
|
|
/* Create the tool's directory lock. */
|
|
result[0].wa_Lock = Lock(path, ACCESS_READ);
|
|
/* Restore original string. */
|
|
*file_part = t;
|
|
if (result[0].wa_Lock == NULL)
|
|
goto create_args_failed;
|
|
/* Copy the tool's name. */
|
|
if ((result[0].wa_Name = copy_of(file_part)) == NULL)
|
|
goto create_args_failed;
|
|
/* The rest of the array is just a copy of the AppMessage array. */
|
|
if (args_size > 0)
|
|
memcpy(result + 1, arg_list, args_size);
|
|
return result;
|
|
|
|
create_args_failed:
|
|
free_args(result, num_args + 1);
|
|
return NULL;
|
|
}
|
|
/* This function is called whenever a tool we started quits. At this point,
|
|
we reply to the workbench.library so it can free the arguments that we
|
|
borrowed. Called indirectly by tr_clean_up(), so we must not clean up
|
|
anything needed by reply_app_msg() until after the call to tr_clean_up().
|
|
*/
|
|
static void reply_app_msg(struct WBArg *arg_list, LONG num_args,
|
|
struct AppMessage *app_message)
|
|
{
|
|
if (arg_list != NULL)
|
|
free_args(arg_list, num_args);
|
|
ReplyMsg((struct Message *) app_message);
|
|
}
|
|
|
|
static void handle_app_menu_item_msg(struct AppMessage *msg)
|
|
{
|
|
Tool *t = (Tool *) msg->am_UserData;
|
|
struct WBArg *args = NULL;
|
|
LONG num_args = msg->am_NumArgs + 1;
|
|
|
|
/* Check that the path isn't empty and that the tool hasn't been removed
|
|
prior to handling this event, then create the Workbench arguments and
|
|
run the tool. */
|
|
if (*t->path == '\0' || !is_in_list(tools, &t->node) ||
|
|
(args = create_args(t->path,msg->am_ArgList,msg->am_NumArgs)) == NULL ||
|
|
!tr_run_tool(args, num_args, reply_app_msg, msg))
|
|
/* Failed to run, reply to the AppMessage right away. */
|
|
reply_app_msg(args, num_args, msg);
|
|
}
|
|
|
|
ULONG wb_set_up()
|
|
{
|
|
if ((wb_port = CreateMsgPort()) == NULL)
|
|
exit(RETURN_FAIL);
|
|
return 1UL << wb_port->mp_SigBit;
|
|
}
|
|
|
|
struct AppWindow *wb_add_window(struct Window *window)
|
|
{
|
|
return AddAppWindow(0, 0, window, wb_port, TAG_DONE);
|
|
}
|
|
|
|
void wb_remove_window(struct AppWindow *app_window)
|
|
{
|
|
RemoveAppWindow(app_window);
|
|
}
|
|
|
|
void wb_add_tool(Tool *tool)
|
|
{
|
|
tool->menu_item = AddAppMenuItemA(0, (ULONG) tool, tool->node.ln_Name,
|
|
wb_port, TAG_DONE);
|
|
}
|
|
|
|
void wb_remove_tool(Tool *tool)
|
|
{
|
|
RemoveAppMenuItem(tool->menu_item);
|
|
tool->menu_item = NULL;
|
|
}
|
|
|
|
void wb_handle_signal(void)
|
|
{
|
|
struct AppMessage *msg;
|
|
|
|
while ((msg = (struct AppMessage *) GetMsg(wb_port)) != NULL)
|
|
switch (msg->am_Type) {
|
|
case AMTYPE_APPWINDOW:
|
|
handle_app_window_msg(msg);
|
|
break;
|
|
case AMTYPE_APPMENUITEM:
|
|
handle_app_menu_item_msg(msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void wb_clean_up()
|
|
{
|
|
delete_port(wb_port);
|
|
}
|