跳转至内容

Aros/开发者/文档/库/GadTools

来自Wikibooks,开放世界中的开放书籍
Aros电子书的导航栏
Aros用户
Aros用户文档
Aros用户常见问题
Aros用户应用程序
Aros用户DOS Shell
Aros/用户/AmigaLegacy
Aros开发文档
Aros开发者文档
从AmigaOS/SDL移植软件
Zune初学者指南
Zune .MUI类
SDL初学者指南
Aros开发者构建系统
特定平台
Aros x86完整系统HCL
Aros x86音频/视频支持
Aros x86网络支持
Aros Intel AMD x86安装
Aros存储支持IDE SATA等
Aros Poseidon USB支持
x86-64支持
摩托罗拉68k Amiga支持
Linux和FreeBSD支持
Windows Mingw和MacOSX支持
Android支持
Arm Raspberry Pi支持
PPC Power Architecture
其他
Aros公共许可证
  • V34 - OS1.3x Gadtools不存在,但gadtools13.library存在
  • V36 - OS2.0x 首次引入
  • V37 - OS2.04 NewLook渲染方案
  • V39 - OS3.0x 添加了NewLook菜单 - 添加了GT_GetGadgetAttrs() -
  • V40 - OS3.1x 修复


在AmigaOS™ 2.0之前,没有统一的界面设计标准——应用程序开发者必须编写自己的对象(按钮、请求器和菜单),Intuition提供最小的支持。AmigaOS™ 2.0带来了gadtools.library,它提供了标准的小部件集,以及界面样式指南,解释了如何布局应用程序以确保用户的一致性。

您应该参考GadTools库章节Amiga列表

Gadtools是一个已弃用的接口,因为它有限制性(在某些情况下确实有其优势)。尝试仅使用BOOPSI gadgets,这将导致我们称为Zune的MUI版本。BOOPSI是MUI、bgui等的基础。


许多GadTools函数使用TagItem数组或标签列表在函数接口之间传递信息。这些基于标签的函数有两种类型,一种采用指向TagItem数组的指针,另一种直接在函数调用中采用可变数量的TagItem参数。通常,第二种形式(通常称为varargs形式,因为调用采用可变数量的参数)是为了方便而提供的,并在内部转换为第一种形式。

所有Gadtools标签都以“GT”开头。通常,它们还具有表示相关Gadgets类型的两个字母的助记符。例如,滑块gadgets识别诸如“GTSL_Level”之类的标签。

对于大多数Gadgets,NewGadget结构用于指定其公共属性。特定Gadgets类型的唯一属性被指定为发送到CreateGadget()函数的标签。

各种GadTools Gadgets类型需要某些类别的IDCMP消息才能工作。应用程序在窗口打开时或稍后使用ModifyIDCMP()指定这些IDCMP类。每种GadTools Gadgets都需要这些IDCMP类中的一种或多种。

IDCMP_GADGETUP, IDCMP_GADGETDOWN, IDCMP_MOUSEMOVE, IDCMP_MOUSEBUTTONS and IDCMP_INTUITICKS. 

关闭窗口后,必须释放使用CreateGadget()分配的Gadgets。


窗口坐标到GadTools Gadgets坐标的直接转换。GaDTools用户界面易于使用,但Gadgets坐标除外。还需要一个基于这些坐标的绘制矩形函数来校准我的绘图区域和擦除矩形坐标。


对GadTools Gadgets允许使用一组严格的函数和操作。

切勿选择性或强制刷新Gadgets。唯一应执行的Gadgets刷新是在窗口使用GadTools Gadgets附加后打开后进行的初始GT_RefreshWindow()。在窗口打开后也可以通过调用AddGlist()和RefreshGlist(),然后调用GT_RefreshWindow()来添加Gadgets。这些刷新函数不应该在任何其他时间调用。

GadTools Gadgets不得相互重叠,不得与其他Gadgets或其他元素重叠。这样做以修改Gadgets的外观不受支持。

GadTools Gadgets不得从窗口中选择性地添加或删除。这与每次调用CreateGadget()产生的Intuition Gadgets数量以及刷新限制有关。

切勿使用OnGadget()或OffGadget()或直接修改GFLG_DISABLED Flags位。禁用或启用Gadgets的唯一批准方法是使用GT_SetGadgetAttrs()和GA_Disabled标签。不支持GA_Disabled的那些Gadgets类型可能无法禁用。

应用程序绝不应写入Gadget结构或任何需要它的结构的任何字段,除非它们是显式的程序员字段(例如GadgetID和UserData),或者它们是保证有意义的。

(LeftEdge, TopEdge, Width, Height, Flags). 

有时,程序会被特别邀请读取某个字段,例如StringInfo->Buffer字段。

GadTools Gadgets不得设置为相对大小或相对定位。这意味着不得指定Gadgets标志GFLG_RELWIDTH、GFLG_RELHEIGHT、GFLG_RELBOTTOM和GFLG_RELRIGHT。Gadgets的激活类型不得修改(例如,将GACT_IMMEDIATE更改为GACT_RELVERIFY)。


Gadgets类型 描述或示例用法
按钮 熟悉的动作gadgets,例如“确定”或“取消”。
字符串 用于文本输入。
整数 用于数字输入。
复选框 用于开关项目。
互斥 单选按钮,在多个选项中选择一个。
循环 多选,从少量选项中选择一个。
滑块 指示范围内的级别。
滚动条 指示列表或区域中的位置。
列表视图 文本的滚动列表。
调色板 颜色选择。
文本显示 只读文本。
数字显示 只读数字。


创建http://thomas-rapp.homepage.t-online.de/examples/gadtools.c


要更改Gadgets显示后标志和主体变量,程序可以调用Intuition的NewModifyProp()。

void NewModifyProp( struct Gadget *gadget, struct Window *window, struct Requester *requester, 
                    unsigned long flags, unsigned long horizPot, unsigned long vertPot,
                       unsigned long horizBody, unsigned long vertBody, long numGad );

Gadgets的内部状态将重新计算,并且图像将重新显示以显示新状态。当numGads(在上面的原型中)设置为全1时,NewModifyProp()将仅更新已更改的部分,这比删除Gadgets、更改值、添加Gadgets并刷新要快得多。

每种GadTools Gadgets都需要这些IDCMP类中的一种或多种:IDCMP_GADGETUP、IDCMP_GADGETDOWN、IDCMP_MOUSEMOVE、IDCMP_MOUSEBUTTONS和IDCMP_INTUITICKS。

使用Gadgets的程序始终需要关于窗口刷新事件的通知。即使应用程序没有执行自己的渲染,它也可能不使用WFLG_NOCAREREFRESH窗口标志,并且必须始终设置IDCMP_REFRESHWINDOW。

Gadgets的属性在创建Gadgets时设置。其中一些属性可以通过使用GT_SetGadgetAttrs()函数稍后更改。

   void GT_SetGadgetAttrs (struct Gadget *gad, struct Window *win,
                           struct Requester *req, Tag tag1, ... )
   void GT_SetGadgetAttrsA(struct Gadget *gad, struct Window *win,
                           struct Requester *req, struct TagItem *taglist)


按钮gadgets(BUTTON_KIND)可能是最简单的GadTools Gadgets。

文本输入(STRING_KIND)和数字输入(INTEGER_KIND)gadgets是相当典型的Intuition字符串gadgets。

循环gadgets(CYCLE_KIND)允许用户从多个选项中准确选择一个。


GadTools Gadgets和菜单需要有关其将显示在其上的屏幕的信息。在创建任何GadTools Gadgets或菜单之前,程序必须使用GetVisualInfo()调用获取此信息。


菜单。GadTools完全支持Intuition的NewLook菜单。可以通过提供以下内容将NewLook菜单添加到应用程序中:

{WA_NewLookMenus, TRUE} tag to OpenWindowTags(),

并提供以下内容:

{GTMN_NewLookMenus, TRUE} tag to LayoutMenus(). 

这两个标签将为您的应用程序提供 NewLook 菜单。用户可以通过调色板首选项编辑器控制用于渲染这些菜单的画笔。

您现在可以在菜单的右侧放置任意命令字符串,Amiga 键等效项通常位于此处。要执行此操作,请将 NewMenu.nm_CommKey 字段指向该字符串(例如,“Shift-Alt-F1”),并在 NewMenu.nm_Flags 中设置新的 NM_COMMANDSTRING 标志。

GT_GetGadgetAttrs()。GadTools 现在有一个 GT_GetGadgetAttrsA() 函数,它根据标签列表中选择的属性检索指定组件的属性。对于标签列表中的每个条目,ti_Tag 标识属性,而 ti_Data 是指向您希望将结果存储在其中的长整型变量的指针。

     LONG top = 0;
     LONG selected = 0;
     LONG result;
     result = GT_GetGadgetAttrs(listview_gad, win, NULL,
                                GTLV_Top, &top,
                                GTLV_Selected, &selected,
                                TAG_DONE);
     if (result != 2)
     {
         printf( "Something's wrong!" );
     }


字符串

[编辑 | 编辑源代码]

大多数常规 Intuition 字符串组件默认为 FALSE


列表视图

[编辑 | 编辑源代码]

列表视图。GadTools 列表视图

滚动列表区域底部的显示框消失。它不再在显示框中显示选定的项目,而是将选定的项目在滚动列表中突出显示。这样做是为了为列表视图准备多选支持。多选需要突出显示方案,因为显示框将无法工作。移除显示框会对列表视图的大小造成轻微影响。

GTLV_CallBack。此标签允许为 Gadtools 提供回调钩子以进行列表视图处理。目前,该钩子仅在渲染单个项目时被调用。每次 GadTools 希望渲染列表视图中的项目时,它都会调用回调函数,该函数可以执行自定义渲染。这使得 GadTools 列表视图可以用于滚动复杂项目,例如图形和图像。

列表视图现在可以使用 {GA_Disabled, TRUE} 禁用。


调色板

[编辑 | 编辑源代码]

调色板。GadTools 调色板组件不再显示一个填充选定颜色的框。选定颜色现在由在主调色板区域中绘制在颜色方块周围的框表示。此更改会略微影响调色板组件的大小。

另一个可能影响调色板组件大小的更改是颜色方块的更智能布局。现在尝试根据从图形数据库中获取的纵横比信息,使颜色方块尽可能地正方形。屏幕上会放置尽可能多的颜色方块,直到它们变得太小,在这种情况下,上面的颜色将被丢弃。GTPA_ColorTable 标签是在稀疏颜色表的支持下添加的。它允许您定义任意画笔以用于填充调色板组件的颜色方块。

GTPA_NumColors 标签允许您定义在调色板组件中显示的颜色确切数量。在 V37 下,GTPA_Depth 标签发挥着相同的作用。GTPA_Depth 的问题是只能指定颜色数量的 2 的倍数。GTPA_NumColors 允许任何数量的颜色。


http://thomas-rapp.homepage.t-online.de/examples/gtmenu.c

设置 GadTools 菜单

GetVisualInfo() and FreeVisualInfo()    CreateContext()


下划线字符“_”是推荐的标记符号。因此,例如,要将字母“F”标记为“选择字体...”按钮的键盘等效项,请创建组件文本

ng.ng_GadgetText = "Select _Font...";


http://thomas-rapp.homepage.t-online.de/examples/lv.c

当多次调用 CreateGadget()(对于每个组件)时,每个新组件都会自动链接到前一个组件的 NextGadget 字段,从而创建一个组件列表。其次,如果其中一个组件创建失败(通常是由于内存不足,但也可能是其他原因),则对于下一次调用 CreateGadget(),next_gad 将为 NULL,并且 CreateGadget() 将立即失败。这意味着程序可以执行多次连续的 CreateGadget() 调用,并且只需要在最后检查失败。

不能在窗口边框中使用 GadTools 滚动条组件


http://thomas-rapp.homepage.t-online.de/examples/scroll.c http://thomas-rapp.homepage.t-online.de/examples/iconify.c

分配一个包含 imageclass 的对象,然后使用它将图形绘制到按钮中



/*
    Copyright © 1995-2007, The AROS Development Team. All rights reserved.
    $Id: calculator.c 27035 2007-10-07 19:33:35Z mazze $
*/

#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <proto/locale.h>
#include <proto/alib.h>

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>

#define ARG_TEMPLATE "PUBSCREEN,TAPE/K"

enum {ARG_PUBSCREEN,ARG_TAPE,NUM_ARGS};

#define MAX_VAL_LEN 13

#define INNER_SPACING_X 4
#define INNER_SPACING_Y 4

#define BUTTON_SPACING_X 4
#define BUTTON_SPACING_Y 4

#define BUTTON_LED_SPACING 4

#define NUM_BUTTONS 20
#define NUM_BUTTON_COLS 5
#define NUM_BUTTON_ROWS 4

#define BUTTON_EXTRA_WIDTH 8
#define BUTTON_EXTRA_HEIGHT 4

#define LED_EXTRA_HEIGHT 4

enum
{
    STATE_LEFTVAL, STATE_OP, STATE_RIGHTVAL, STATE_EQU
};

enum
{
    BTYPE_0,
    BTYPE_1,
    BTYPE_2,
    BTYPE_3,
    BTYPE_4,
    BTYPE_5,
    BTYPE_6,
    BTYPE_7,
    BTYPE_8,
    BTYPE_9,
    BTYPE_COMMA,
    BTYPE_BS,
    BTYPE_CA,
    BTYPE_CE,
    BTYPE_MUL,
    BTYPE_DIV,
    BTYPE_SUB,
    BTYPE_ADD,
    BTYPE_SIGN,
    BTYPE_EQU,
    
    BTYPE_LED
};

struct ButtonInfo
{
    char *text;
    WORD type;
    char key1;
    char key2;
};

static struct ButtonInfo bi[NUM_BUTTONS] =
{
    {"7"	,BTYPE_7	, '7'	, 0	},
    {"8"	,BTYPE_8	, '8'	, 0	},
    {"9"	,BTYPE_9	, '9'	, 0	},
    {"CA"	,BTYPE_CA	, 'A'	, 127	},
    {"CE"	,BTYPE_CE	, 'E'	, 0	},
    
    {"4"	,BTYPE_4	, '4'	, 0	},
    {"5"	,BTYPE_5	, '5'	, 0	},
    {"6"	,BTYPE_6	, '6'	, 0	},
    {"×"	,BTYPE_MUL	, '*'	, 'X'	},
    {":"	,BTYPE_DIV	, '/'	, ':'	},
    
    {"1"	,BTYPE_1	, '1'	, 0	},
    {"2"	,BTYPE_2	, '2'	, 0	},
    {"3"	,BTYPE_3	, '3'	, 0	},
    {"+"	,BTYPE_ADD	, '+'	, 0	},
    {"-"	,BTYPE_SUB	, '-'	, 0	},
    
    {"0"	,BTYPE_0	, '0'	, 0	},
    {"."	,BTYPE_COMMA	, '.'	, ','	},
    {"«"	,BTYPE_BS	, 8  	, 0	},
    {"±"	,BTYPE_SIGN	, 'S'	, 0	},
    {"="	,BTYPE_EQU	, '='	, 13	}
};


struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;
#ifndef __MORPHOS__
struct LocaleBase *LocaleBase;
#else
struct Library *LocaleBase;
#endif

static struct Screen *scr;
static struct DrawInfo *dri;
static struct Gadget *gadlist, *gad[NUM_BUTTONS + 2];
static struct Window *win;
static struct RDArgs *MyArgs;
static APTR vi;
static BPTR tapefh;

static WORD win_borderleft,win_bordertop;
static WORD buttonwidth,buttonheight,ledheight;
static WORD inner_winwidth,inner_winheight;
static WORD vallen,state,operation;

static BOOL dotape;

static double leftval,rightval;

static char comma,*pubscrname;
static char ledstring[256],visledstring[256],
				tempstring[256],tapename[256];

static char *deftapename = "RAW:%ld/%ld/%ld/%ld/Calculator Tape/INACTIVE/SCREEN%s";

UBYTE version[] = "$VER: Calculator 1.3 (07.10.2007) © AROS Dev Team";

static IPTR Args[NUM_ARGS];

static void Cleanup(char *msg)
{
    WORD rc;
    
    if (msg)
    {
	printf("Calculator: %s\n",msg);
	rc = RETURN_WARN;
    } else {
	rc = RETURN_OK;
    }
    
    if (tapefh) Close(tapefh);
    
    if (win) CloseWindow(win);
    
    if (gadlist) FreeGadgets(gadlist);
    
    if (vi) FreeVisualInfo(vi);
    if (dri) FreeScreenDrawInfo(scr,dri);
    if (scr) UnlockPubScreen(0,scr);
    
    if (MyArgs) FreeArgs(MyArgs);
    
    if (LocaleBase) CloseLibrary((struct Library *)LocaleBase);
    if (GadToolsBase) CloseLibrary(GadToolsBase);
    if (GfxBase) CloseLibrary((struct Library *)GfxBase);
    if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
    
    exit (rc);
}

static void DosError(void)
{
    Fault(IoErr(),0,tempstring,255);
    Cleanup(tempstring);
}

static void OpenLibs(void)
{
    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",39)))
    {
	Cleanup("Can't open intuition.library V39!");
    }
    
    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",39)))
    {
	Cleanup("Can't open graphics.library V39!");
    }
    
    if (!(GadToolsBase = OpenLibrary("gadtools.library",39)))
    {
	Cleanup("Can't open gadtools.library V39!");
    }
    
    LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",39);
}

static void GetArguments(void)
{
    if (!(MyArgs = ReadArgs(ARG_TEMPLATE,(IPTR *)Args,0)))
    {
	DosError();
    }
    
    pubscrname = (char *)Args[ARG_PUBSCREEN];
    
    if (Args[ARG_TAPE])
    {
	strcpy(tapename,(char *)Args[ARG_TAPE]);
	dotape = TRUE;
    }
}

static void DoLocale(void)
{
    struct Locale *loc;
    
    comma = '.';
    
    if ((loc = OpenLocale(0)))
    {
    	comma = loc->loc_DecimalPoint[0];
    	CloseLocale(loc);
    }
    
    bi[16].text[0] = comma;
}

static void GetVisual(void)
{
    if (pubscrname) scr = LockPubScreen(pubscrname);
    
    if (!scr)
    {
	if (!(scr = LockPubScreen(0)))
	{
	    Cleanup("Can't lock screen!");
	}
    }
    
    if (!(dri = GetScreenDrawInfo(scr)))
    {
	Cleanup("Can't get drawinfo!");
    }
    
    if (!(vi = GetVisualInfo(scr,0)))
    {
	Cleanup("Can't get visual info!");
    }
    
    win_borderleft = scr->WBorLeft;

    /* SDuvan: was scr->WBorTop + scr->Font->ta_YSize + 1 */
    win_bordertop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;

}

static void InitGUI(void)
{
    static struct RastPort temprp;
    
    WORD i,len;
    
    InitRastPort(&temprp);
    SetFont(&temprp,dri->dri_Font);
    
    buttonheight = dri->dri_Font->tf_YSize + BUTTON_EXTRA_HEIGHT;
    
    for(i = 0;i < NUM_BUTTONS;i++)
    {
	len = TextLength(&temprp,bi[i].text,strlen(bi[i].text));
	if (len > buttonwidth) buttonwidth = len;
    }
    
    buttonwidth += BUTTON_EXTRA_WIDTH;
    
    ledheight = dri->dri_Font->tf_YSize + LED_EXTRA_HEIGHT;
    
    inner_winwidth = buttonwidth * NUM_BUTTON_COLS +
	BUTTON_SPACING_X * (NUM_BUTTON_COLS - 1) + 
	INNER_SPACING_X * 2;
    
    inner_winheight = buttonheight * NUM_BUTTON_ROWS +
	BUTTON_SPACING_Y * (NUM_BUTTON_ROWS - 1) +
	BUTTON_LED_SPACING +
	ledheight +
	INNER_SPACING_Y * 2;
    
#ifdef __AROS__
    DeinitRastPort(&temprp);
#endif
    strcpy(ledstring,"0");
}

static void MakeGadgets(void)
{
    struct Gadget *mygad = 0;
    struct NewGadget ng = {0};
    WORD col,row,i;
    
    ng.ng_VisualInfo = vi;
    
    mygad = CreateContext(&gadlist);
    
    ng.ng_GadgetID = BTYPE_LED;
    
    ng.ng_LeftEdge = win_borderleft + INNER_SPACING_X;
    ng.ng_TopEdge  = win_bordertop + INNER_SPACING_Y;
    ng.ng_Width = inner_winwidth - INNER_SPACING_X * 2;
    ng.ng_Height = ledheight;
    
    mygad = gad[BTYPE_LED] = CreateGadget(TEXT_KIND,
					  mygad,
					  &ng,
					  GTTX_Text, (IPTR) ledstring,
					  GTTX_CopyText,TRUE,
					  GTTX_Border,TRUE,
					  GTTX_Justification,GTJ_RIGHT,
					  TAG_DONE);
    
    i = 0;
    
    ng.ng_TopEdge = win_bordertop +
	INNER_SPACING_Y + 
	ledheight +
	BUTTON_LED_SPACING;
    
    ng.ng_Width = buttonwidth;
    ng.ng_Height = buttonheight;
    
    for(row = 0; row < NUM_BUTTON_ROWS; row++)
    {
	for(col = 0; col < NUM_BUTTON_COLS; col++, i++)
	{
	    ng.ng_GadgetID = bi[i].type;
	    
	    ng.ng_LeftEdge = win_borderleft +
		INNER_SPACING_X +
		col * (buttonwidth + BUTTON_SPACING_X);
	    
	    ng.ng_GadgetText = bi[i].text;
	    
	    mygad = gad[bi[i].type] = CreateGadgetA(BUTTON_KIND,
						    mygad,
						    &ng,
						    0);
	    
	} /* for(col = 0;col < NUM_BUTTON_COLS; col++) */
	
	ng.ng_TopEdge += buttonheight + BUTTON_SPACING_Y;
	
    } /* for(row = 0; row < NUM_BUTTON_ROWS; row++) */
    
    if (!mygad)
    {
	Cleanup("Can't create gadgets!");
    }
    
}

static void MakeWin(void)
{
    win = OpenWindowTags(0,WA_PubScreen,(IPTR)scr,
			 WA_Left,scr->MouseX,
			 WA_Top,scr->MouseY,
			 WA_InnerWidth,inner_winwidth,
			 WA_InnerHeight,inner_winheight,
			 WA_AutoAdjust,TRUE,
			 WA_Title,(IPTR)"Calculator",
			 WA_CloseGadget,TRUE,
			 WA_DepthGadget,TRUE,
			 WA_DragBar,TRUE,
			 WA_Activate,TRUE,
			 WA_SimpleRefresh,TRUE,
			 WA_IDCMP,IDCMP_CLOSEWINDOW |
			 IDCMP_GADGETUP |
			 IDCMP_VANILLAKEY |
			 IDCMP_RAWKEY |
			 IDCMP_REFRESHWINDOW,
			 WA_Gadgets,(IPTR)gadlist,
			 TAG_DONE);

    if (!win) Cleanup("Can't open window!");
    
    GT_RefreshWindow(win,0);
    
    ScreenToFront(win->WScreen);
}

static void OpenTape(void)
{
    struct List *l;
    struct PubScreenNode *psn;
    char *scrname = "";
    WORD x,y,w,h;
    
    if (!(tapename[0]))
    {
	l = LockPubScreenList();
	
	psn = (struct PubScreenNode *)l->lh_Head;
	
	while (psn->psn_Node.ln_Succ)
	{
	    if (psn->psn_Screen == scr)
	    {
		if (psn->psn_Node.ln_Name)
		{
		    scrname = psn->psn_Node.ln_Name;
		}
		break;
	    }
	    psn = (struct PubScreenNode *)psn->psn_Node.ln_Succ;
	}
	
	UnlockPubScreenList();
	
	w = win->Width * 5 / 4;
	h = win->Height;
	
	x = win->LeftEdge;
	y = win->TopEdge;
	
	if (x > (scr->Width - (x + w)))
	{
	    x -= w;
	} else {
	    x += win->Width;
	}
	sprintf(tapename,deftapename,x,y,w,h,scrname);
    }
    
    if (!(tapefh = Open(tapename,MODE_NEWFILE)))
    {
	DisplayBeep(scr);
    }
}

static double GetValue(void)
{
    double val;
    char c = 0,*sp;
    
    sp = strchr(ledstring,comma);
    if (sp)
    {
	c = *sp;
	*sp = '.';
    }
    
    val = strtod(ledstring,0);
    
    if (sp) *sp = c;
    
    return val;
}

static void GetLeftValue(void)
{	
    leftval = GetValue();
}

static void GetRightValue(void)
{
    rightval = GetValue();
}

static void LeftValToLED(void)
{
    char *sp;
    
    sprintf(ledstring,"%f",leftval);
    
    sp = strchr(ledstring,'.');
    if (!sp) sp = strchr(ledstring,',');
    if (sp) *sp = comma;	
}

static char *DoOperation(void)
{
    char *matherr = 0;
    
    switch (operation)
    {
    case BTYPE_ADD:
	leftval += rightval;
	break;
	
    case BTYPE_SUB:
	leftval -= rightval;
	break;
	
    case BTYPE_MUL:
	leftval *= rightval;
	break;
	
    case BTYPE_DIV:
	if (rightval == 0.0)
	{
	    matherr = "Division by zero!";
	} else {
	    leftval /= rightval;
	}
	break;
    }
    
    if (leftval > 9999999999999.0) // because of MAX_VAL_LEN
    {
	matherr = "Buffer overflow!";
    }

    if (!matherr) LeftValToLED();
    
    return matherr;
}

static void RefreshLED(void)
{
    strcpy(visledstring,ledstring);
    
    if ((ledstring[0] == ',') ||
	(ledstring[0] == '\0') ||
	((ledstring[0] >= '0') && (ledstring[0] <= '9')))
    {
	visledstring[0] = '\0';
	
	if ((ledstring[0] == ',') ||
	    (ledstring[0] == '.') ||
	    (ledstring[0] == '\0'))
	{
	    strcpy(visledstring,"0");
	}
	strcat(visledstring,ledstring);
    }
    
    GT_SetGadgetAttrs(gad[BTYPE_LED],
		      win,
		      0,
		      GTTX_Text,(IPTR)visledstring,
		      TAG_DONE);
}

static void HandleButton(WORD type)
{
    char *matherr = 0;
    WORD checklen;
    BOOL refresh_led = FALSE;
    
    switch(type)
    {
    case BTYPE_0:
    case BTYPE_1:
    case BTYPE_2:
    case BTYPE_3:
    case BTYPE_4:
    case BTYPE_5:
    case BTYPE_6:
    case BTYPE_7:
    case BTYPE_8:
    case BTYPE_9:
	checklen = vallen;
	if ((strchr(ledstring,comma))) checklen--;
	if ((strchr(ledstring,'-'))) checklen--;
	
	if (checklen < MAX_VAL_LEN)
	{
	    if (state == STATE_OP)
	    {
		state = STATE_RIGHTVAL;
	    } else if (state == STATE_EQU)
	    {
		state = STATE_LEFTVAL;
	    }
	    
	    if ((vallen > 0) || (type != BTYPE_0))
	    {
		ledstring[vallen++] = type + '0';
	    }
	    ledstring[vallen] = '\0';
	    
	    refresh_led = TRUE;
	    
	} /* if (vallen < MAX_VAL_LEN) */
	break;
	
    case BTYPE_COMMA:
	if (!strchr(ledstring,comma))
	{
	    if (state == STATE_OP)
	    {
		state = STATE_RIGHTVAL;
	    } else if (state == STATE_EQU)
	    {
		state = STATE_LEFTVAL;
	    }
	    
	    ledstring[vallen++] = comma;
	    ledstring[vallen] = '\0';
	    
	    refresh_led = TRUE;
	    
	} /* if (!strchr(ledstring,comma)) */
	break;
	
    case BTYPE_CA:
	vallen = 0;
	leftval = 0.0;
	rightval = 0.0;
	operation = BTYPE_ADD;
	
	state = STATE_LEFTVAL;
	
	strcpy(ledstring,"0");
	refresh_led = TRUE;
	
	if (tapefh) FPutC(tapefh, '\n');
	break;
	
    case BTYPE_CE:
	vallen = 0;
	strcpy(ledstring,"0");
	refresh_led = TRUE;
	
	switch (state)
	{
	case STATE_LEFTVAL:
	    leftval = 0.0;
	    break;
	    
	case STATE_OP:
	case STATE_RIGHTVAL:
	    rightval = 0.0;
	    break;
	}
	break;
	
    case BTYPE_BS:
	if (vallen)
	{
	    ledstring[--vallen] = '\0';
	    if (vallen == 0) strcpy(ledstring,"0");				
	    refresh_led = TRUE;
	}
	break;
	
    case BTYPE_SIGN:
	switch(state)
	{
	case STATE_LEFTVAL:
	case STATE_RIGHTVAL:
	    if (ledstring[0] == '-')
	    {
		strcpy(ledstring,&ledstring[1]);
	    } else {
		strcpy(tempstring,ledstring);
		strcpy(ledstring,"-");
		strcat(ledstring,tempstring);
	    }
	    refresh_led = TRUE;
	    break;
	    
	case STATE_EQU:
	    leftval = -leftval;
	    LeftValToLED();
	    refresh_led = TRUE;
	    break;
	}
	break;
	
    case BTYPE_ADD:
    case BTYPE_SUB:
    case BTYPE_MUL:
    case BTYPE_DIV:
	switch(state)
	{
	case STATE_LEFTVAL:
	case STATE_EQU:
	    GetLeftValue();
	    rightval = leftval;
	    
	    state = STATE_OP;
	    vallen = 0;
	    strcpy(ledstring,"0");
	    
	    if (tapefh)
	    {
		FPutC(tapefh, '\t');
		FPuts(tapefh, visledstring);
		FPutC(tapefh, '\n');
	        Flush(tapefh);
	    }
	    break;

	case STATE_OP:
	    break;
	    
	case STATE_RIGHTVAL:
	    GetRightValue();
	    matherr = DoOperation();
	    state = STATE_OP;
	    vallen = 0;				
	    refresh_led = TRUE;
	    
	    if (tapefh)
	    {
		FPuts(tapefh,
				(operation == BTYPE_ADD) ? "+" :
				(operation == BTYPE_SUB) ? "-" :
				(operation == BTYPE_DIV) ? ":" :
				"×");
		FPutC(tapefh, '\t');
		FPuts(tapefh, visledstring);
		FPutC(tapefh, '\n');
		Flush(tapefh);
	    }
	    break;
	    
	} /* switch(state) */
	
	operation = type;
	break;
	
    case BTYPE_EQU:
	if (state == STATE_LEFTVAL)
	{
	    GetLeftValue();
	    if (tapefh)
	    {
		FPutC(tapefh, '\t');
		FPuts(tapefh, visledstring);
		FPutC(tapefh, '\n');
		Flush(tapefh);
	    }
	}	
	else if (state == STATE_RIGHTVAL)
	{
	    GetRightValue();
	    if (tapefh)
	    {
		FPuts(tapefh, 
				(operation == BTYPE_ADD) ? "+" :
				(operation == BTYPE_SUB) ? "-" :
				(operation == BTYPE_DIV) ? ":" :
				"×");
		FPutC(tapefh, '\t');
		FPuts(tapefh, visledstring);
		FPutC(tapefh, '\n');
		Flush(tapefh);
	    }
	}
	
	matherr = DoOperation();
	state = STATE_EQU;
	
	vallen = 0;
	
	if (!matherr)
	{
	    RefreshLED();
	    if (tapefh)
	    {
		FPuts(tapefh, "=\t");
		FPuts(tapefh, visledstring);
		FPutC(tapefh, '\n');
		Flush(tapefh);
	    }
	} else {
	    refresh_led = TRUE;
	}
	break;
	
    } /* switch(type) */
    
    if (matherr)
    {
	leftval = rightval = 0.0;
	state = STATE_LEFTVAL;
	operation = BTYPE_ADD;
	vallen = 0;
	strcpy(ledstring,matherr);
	refresh_led = TRUE;
    }
    
    if (refresh_led) RefreshLED();
    
}

static void HandleAll(void)
{
    struct IntuiMessage *msg;
    WORD icode,i;
    ULONG signals;
    
    BOOL quitme = FALSE;
    
    if (dotape) OpenTape();

    while(!quitme)
    {
	signals = Wait(1L << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);

	if (signals & (1L << win->UserPort->mp_SigBit))
	{
	    while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
	    {
	        switch(msg->Class)
	        {
	        case IDCMP_CLOSEWINDOW:
		    quitme = TRUE;
		    break;
		
	        case IDCMP_REFRESHWINDOW:
		    GT_BeginRefresh(win);
		    GT_EndRefresh(win,TRUE);
		    break;
		
	        case IDCMP_GADGETUP:
		    HandleButton(((struct Gadget *)msg->IAddress)->GadgetID);
		    break;
		
	        case IDCMP_VANILLAKEY:
		    icode = toupper(msg->Code);
		
		    for(i = 0;i < NUM_BUTTONS;i++)
		    {
		        if ((icode == bi[i].key1) ||
			    (icode == bi[i].key2))
		        {
			    icode = bi[i].type;
			    break;
		        }
		    }
		    if (i < NUM_BUTTONS)
		    {
		        HandleButton(icode);
		    } else if (icode == 27)
		    {
		        quitme = TRUE;
		    }
		    break;
		
	        } /* switch(msg->Class) */
	    
	        ReplyMsg((struct Message *)msg);
	    } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
	} /* if(signals & (1L << win->UserPort->mp_SigBit)) */
	if (signals & SIGBREAKF_CTRL_C)
	    quitme = TRUE;

    } /* while(!quitme) */
}

int main(void)
{
    OpenLibs();
    GetArguments();
    DoLocale();
    GetVisual();
    InitGUI();
    MakeGadgets();
    MakeWin();
    HandleAll();
    Cleanup(0);
    return 0;
}




/* Menus for LiteBench */

#ifdef WB_1.3
/* 
 * Workbench 1.3 style menus (obsolete)
 * 
 * Workbench		
 *   Open	
 *   Close
 *   Duplicate
 *   Rename
 *   Info
 *   Discard
 * 
 * Disk
 *   Empty Disk
 *   Initialize
 *
 *  Special
 *    Clean up
 *    Last error
 *    Redraw
 *    Snapshot
 *    Version
*/
struct NewMenu mynewmenu[] =
    {
        { NM_TITLE, "Workbench",          0, 0, 0, 0, },
        {  NM_ITEM,   "Open"              0  0, 0, 0, },
        {  NM_ITEM,   "Close",    	  0, 0, 0, 0, },
        {  NM_ITEM,   "Duplicate",        0, 0, 0, 0, },
        {  NM_ITEM,   "Rename",           0, 0, 0, 0, },
        {  NM_ITEM,   "Info",             0, 0, 0, 0, },
        {  NM_ITEM,   "Discard",          0, 0, 0, 0, },
        
        { NM_TITLE, "Disk",               0, 0, 0, 0, },
        {   NM_ITEM,  "Empty Disk",       0, 0, 0, 0, },
        {   NM_ITEM,  "Initialize",       0, 0, 0, 0, },

        { NM_TITLE, "Special",            0, 0, 0, 0, },
        {   NM_ITEM, "Clean Up",          0, 0, 0, 0, },
        {   NM_ITEM, "Last Error"         0, 0, 0, 0, },
        {   NM_ITEM, "Redraw",            0, 0, 0, 0, },
        {   NM_ITEM, "Snapshot",          0, 0, 0, 0, },
        {   NM_ITEM, "Version",           0, 0, 0, 0, },
        
        {   NM_END, NULL,              0, 0, 0, 0, },
    };

#endif /* WB_1.3 */

#ifdef LITEBENCH
/* simplified menus for a minimal workbench program */
struct NewMenu mynewmenu[] =
    {
        { NM_TITLE, "Icon",          0, 0, 0, 0, },
        {   NM_ITEM, "Open",             "O", 0, 0, 0, },
        {   NM_ITEM, "Copy",             "C", 0, 0, 0, },
        {   NM_ITEM, "Rename...",        "R", 0, 0, 0, },
        {   NM_ITEM, "Information...",   "I", 0, 0, 0, },
        {   NM_ITEM, "Snapshot",         "S", 0, 0, 0, },
        {   NM_ITEM, "Unsnapshot",       "U", 0, 0, 0, },
        {   NM_ITEM, "Leave out",        "L", 0, 0, 0, },
        {   NM_ITEM, "Put away",         "P", 0, 0, 0, },
        {   NM_ITEM, NM_BARLABEL,          0, 0, 0, 0, },
        {   NM_ITEM, "Delete...",          0, 0, 0, 0, },
        {   NM_ITEM, "Format...",          0, 0, 0, 0, },
        {   NM_ITEM, "Empty trash",        0, 0, 0, 0, },

        { NM_TITLE, "Window",             0, 0, 0, 0, },
        {   NM_ITEM,  "New drawer",        "N", 0, 0, 0, },
        {   NM_ITEM,  "Open parent",       "K", 0, 0, 0, },
        {   NM_ITEM,  "Close",               0, 0, 0, 0, },
        {   NM_ITEM,  "Update",              0, 0, 0, 0, }, 
        {   NM_ITEM,  "Select contents",   "A", 0, 0, 0, },

        {   NM_ITEM, "Clean up by",        0, 0, 0, 0, },
        {     NM_SUB,   "Column",        ".", 0, 0, 0, },
        {     NM_SUB,   NM_BARLABEL,       0, 0, 0, 0, },
        {     NM_SUB,   "Name",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Date",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Size",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Type",            0, (CHECKIT), 0, 0, },

        {   NM_ITEM, "Resize to fit",      0, 0, 0, 0, },
 
        {   NM_ITEM, "Snapshot",           0, 0, 0, 0, },
        {     NM_SUB,  "Window",            0, 0, 0, 0, },
        {     NM_SUB,  "All",               0, 0, 0, 0, },

        {   NM_ITEM, "Show",                0, 0, 0, 0, },
        {     NM_SUB, "Only icons",       "-", 0, 0, 0, },
        {     NM_SUB, "All files",        "+", 0, 0, 0, },

        {   NM_ITEM, "View by",             0, 0, 0, 0, },
        {     NM_SUB,   "Icon",           "1", 0, 0, 0, },
        {     NM_SUB, NM_BARLABEL,         0 , 0, 0, 0, },
        {     NM_SUB, "Name",             "2", 0, 0, 0, },
        {     NM_SUB, "Date",             "3", 0, 0, 0, },
        {     NM_SUB, "Size",             "4", 0, 0, 0, },
        {     NM_SUB, "Type",             "5", 0, 0, 0, },

		{ NM_TITLE, "Special"			0, 0, 0, 0, },
		{   NM_ITEM, "New Shell..."		"W",0,0,0, },
		{   NM_ITEM, "Icon Editor..."   "Y",0,0,0, },
 		{   NM_ITEM, NM_BARLABEL,		  0, 0, 0, 0, },
        {   NM_ITEM, "Quit Litebench", "Q", 0, 0, 0, },  
         
        {   NM_END, NULL,              0, 0, 0, 0, },
    };

#endif /* LITEBENCH */

#ifdef WB_3.x
/*  Workbench 3.x compatible menu strips, same keyboard shortcuts, etc.
 * *
 *  Workbench
 *  x Backdrop [a]B	 
 *  Enter Command [a]E	 
 *  Redraw all		 
 *  Update all		 
 *  Last Message	
 *  About...		
 *  Quit [a]Q	
 *
 * Window
 *  New drawer [a]N
 *  Open parent [a]K
 *  Close
 *  Update
 *  Select Contents [a]A
 *  Clear selection [a]Z
 *  Clean up by >>
 *                 Column [a]. {period}
 *                 -------------------
 *                 Name
 *                 Date
 *                 Size
 *                 Type
 *  Resize to fit
 *  Snapshot    >>
 *                 Window
 *                 All
 *  Show        >>
 *                 Only icons [a] - {minus}
 *                 All files  [a] + {plus}
 *  View by     >>
 *                 Icon       [a] 1 {one}
 *                 ------------------
 *                 Name       [a] 2 {two}
 *                 Date       [a] 3 {three}
 *                 Size       [a] 4 {four}
 *                 Type       [a] 5 {five}
 *
 * Icons
 *  Open [a]O
 *  Copy [a]C
 *  Rename... [a]R
 *  Information... a[I]
 *  Snapshot [a]S
 *  Unsnapshot [a]U
 *  Leave out [a]L
 *  Put away a[P]
 *  -------------------
 *  Delete....
 *  Format....
 *  Empty Trash
 *
 * Tools
 *   ResetWB
 *
 */
struct NewMenu mynewmenu[] =
    {
        { NM_TITLE, "Workbench",          0, 0, 0, 0, },
        {  NM_ITEM,   "Backdrop",         "B", (CHECKIT|CHECKED), 0, 0, },
        {  NM_ITEM,   "Enter command",    "E", 0, 0, 0, },
        {  NM_ITEM,   "Redraw all",         0, 0, 0, 0, },
        {  NM_ITEM,   "Update all",         0, 0, 0, 0, },
        {  NM_ITEM,   "Last message",       0, 0, 0, 0, },
        {  NM_ITEM,   "About...",           0, 0, 0, 0, },
        {  NM_ITEM,   "Quit",             "Q", 0, 0, 0, },
        
        { NM_TITLE, "Window",             0, 0, 0, 0, },
        {   NM_ITEM,  "New drawer",        "N", 0, 0, 0, },
        {   NM_ITEM,  "Open parent",       "K", 0, 0, 0, },
        {   NM_ITEM,  "Close",               0, 0, 0, 0, },
        {   NM_ITEM,  "Update",              0, 0, 0, 0, }, 
        {   NM_ITEM,  "Select contents",   "A", 0, 0, 0, },

        {   NM_ITEM, "Clean up by",        0, 0, 0, 0, },
        {     NM_SUB,   "Column",        ".", 0, 0, 0, },
        {     NM_SUB,   NM_BARLABEL,       0, 0, 0, 0, },
        {     NM_SUB,   "Name",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Date",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Size",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Type",            0, (CHECKIT), 0, 0, },

        {   NM_ITEM, "Resize to fit",      0, 0, 0, 0, },
 
        {   NM_ITEM, "Snapshot",           0, 0, 0, 0, },
        {     NM_SUB,  "Window",            0, 0, 0, 0, },
        {     NM_SUB,  "All",               0, 0, 0, 0, },

        {   NM_ITEM, "Show",                0, 0, 0, 0, },
        {     NM_SUB, "Only icons",       "-", 0, 0, 0, },
        {     NM_SUB, "All files",        "+", 0, 0, 0, },

        {   NM_ITEM, "View by",             0, 0, 0, 0, },
        {     NM_SUB,   "Icon",           "1", 0, 0, 0, },
        {     NM_SUB, NM_BARLABEL,         0 , 0, 0, 0, },
        {     NM_SUB, "Name",             "2", 0, 0, 0, },
        {     NM_SUB, "Date",             "3", 0, 0, 0, },
        {     NM_SUB, "Size",             "4", 0, 0, 0, },
        {     NM_SUB, "Type",             "5", 0, 0, 0, },

        {   NM_ITEM, NM_BARLABEL,           0, 0, 0, 0, },
        {   NM_ITEM, "Find...",           "F", 0, 0, 0, },

        { NM_TITLE, "Icons",               0, 0, 0, 0, },
        {   NM_ITEM, "Open",             "O", 0, 0, 0, },
        {   NM_ITEM, "Copy",             "C", 0, 0, 0, },
        {   NM_ITEM, "Rename...",        "R", 0, 0, 0, },
        {   NM_ITEM, "Information...",   "I", 0, 0, 0, },
        {   NM_ITEM, "Snapshot",         "S", 0, 0, 0, },
        {   NM_ITEM, "Unsnapshot",       "U", 0, 0, 0, },
        {   NM_ITEM, "Leave out",        "L", 0, 0, 0, },
        {   NM_ITEM, "Put away",         "P", 0, 0, 0, },
        {   NM_ITEM, NM_BARLABEL,          0, 0, 0, 0, },
        {   NM_ITEM, "Delete...",          0, 0, 0, 0, },
        {   NM_ITEM, "Format...",          0, 0, 0, 0, },
        {   NM_ITEM, "Empty trash",        0, 0, 0, 0, },

        { NM_TITLE, "Tools",           0, 0, 0, 0, },
        {   NM_ITEM, "ResetWB",        0, 0, 0, 0, },
        
        {   NM_END, NULL,              0, 0, 0, 0, },
    };
#endif /* WB_3.x */

#ifdef AROSbench /* enhanced WB_3.x style for AROS */
struct NewMenu mynewmenu[] =
    {
	{ NM_TITLE, "AROSbench",	    0, 0, 0, 0, },
        {  NM_ITEM,   "Backdrop",      "B", (CHECKIT|CHECKED), 0, 0, },
        {  NM_ITEM,   "Enter command",    "E", 0, 0, 0, },
	{  NM_ITEM,   "New Shell",        "W", 0, 0, 0, },
        {  NM_ITEM,   "Redraw all",         0, 0, 0, 0, },
        {  NM_ITEM,   "Update all",         0, 0, 0, 0, },
        {  NM_ITEM,   "Last message",       0, 0, 0, 0, },
        {  NM_ITEM,   "About AROSbench..."  0, 0, 0, 0, },
	{  NM_ITEM,   "Quit AROSbench",	  "Q", 0, 0, 0, },
	{  NM_ITEM,   NM_BARLABEL,          0, 0, 0, 0, },
	{  NM_ITEM,   "Shutdown AROS...",   0, 0, 0, 0, },

        { NM_TITLE, "Window",             0, 0, 0, 0, },
        {   NM_ITEM,  "New drawer",     "N", 0, 0, 0, },
        {   NM_ITEM,  "Open parent",    "K", 0, 0, 0, },
        {   NM_ITEM,  "Close",            0, 0, 0, 0, },
        {   NM_ITEM,  "Update",           0, 0, 0, 0, }, 
        {   NM_ITEM,  "Select contents","A", 0, 0, 0, },

        {   NM_ITEM, "Clean up by",        0, 0, 0, 0, },
        {     NM_SUB,   "Column",        ".", 0, 0, 0, },
        {     NM_SUB,   NM_BARLABEL,       0, 0, 0, 0, },
        {     NM_SUB,   "Name",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Date",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Size",            0, (CHECKIT), 0, 0, },
        {     NM_SUB,   "Type",            0, (CHECKIT), 0, 0, },

        {   NM_ITEM, "Resize to fit",      0, 0, 0, 0, },
 
        {   NM_ITEM, "Snapshot",           0, 0, 0, 0, },
        {     NM_SUB,  "Window",           0, 0, 0, 0, },
        {     NM_SUB,  "All",              0, 0, 0, 0, },

        {   NM_ITEM, "Show",                0, 0, 0, 0, },
        {     NM_SUB, "Only icons",       "-", 0, 0, 0, },
        {     NM_SUB, "All files",        "+", 0, 0, 0, },

        {   NM_ITEM, "View by",             0, 0, 0, 0, },
        {     NM_SUB, "Icon",             "1", 0, 0, 0, },
        {     NM_SUB, NM_BARLABEL,         0 , 0, 0, 0, },
        {     NM_SUB, "Name",             "2", 0, 0, 0, },
        {     NM_SUB, "Date",             "3", 0, 0, 0, },
        {     NM_SUB, "Size",             "4", 0, 0, 0, },
        {     NM_SUB, "Type",             "5", 0, 0, 0, },

        {   NM_ITEM, NM_BARLABEL,           0, 0, 0, 0, },
        {   NM_ITEM, "Find...",           "F", 0, 0, 0, },

        { NM_TITLE, "Icons",               0, 0, 0, 0, },
        {   NM_ITEM, "Open",             "O", 0, 0, 0, },
        {   NM_ITEM, "Copy",             "C", 0, 0, 0, },
        {   NM_ITEM, "Rename...",        "R", 0, 0, 0, },
        {   NM_ITEM, "Information...",   "I", 0, 0, 0, },
        {   NM_ITEM, "Snapshot",         "S", 0, 0, 0, },
        {   NM_ITEM, "Unsnapshot",       "U", 0, 0, 0, },
        {   NM_ITEM, "Leave out",        "L", 0, 0, 0, },
        {   NM_ITEM, "Put away",         "P", 0, 0, 0, },
        {   NM_ITEM, NM_BARLABEL,          0, 0, 0, 0, },
        {   NM_ITEM, "Delete...",          0, 0, 0, 0, },
        {   NM_ITEM, "Format...",          0, 0, 0, 0, },
        {   NM_ITEM, "Empty trash",        0, 0, 0, 0, },

	{ NM_TITLE, "QuickAccess",	   0, 0, 0, 0, },
	{   NM_ITEM,  "WBstartup files",   0, 0, 0, 0, },
	{   NM_ITEM,  "System preferences",  0, 0, 0, 0, },
	{   NM_ITEM,  "System scripts",    0, 0, 0, 0, },
	{   NM_ITEM,  "System tools",      0, 0, 0, 0, },
	{   NM_ITEM,  "System utilities" , 0, 0, 0, 0, },
	{   NM_ITEM,  "System fonts", 	   0, 0, 0, 0, },
	{   NM_ITEM,  "System deficons",   0, 0, 0, 0, },
	{   NM_ITEM,  "System temporary files",   0, 0, 0, 0, },
	{   NM_ITEM,  "Trashcan", 	   0, 0, 0, 0, },
		

        { NM_TITLE, "Tools",           0, 0, 0, 0, },
        {   NM_END, NULL,              0, 0, 0, 0, },
    };

#endif /* AROSbench */
/* gadtoolsmenu.c*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/gadtools.h>

#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/intuition.h>

#include <stdio.h>

struct Library *GadToolsBase;
struct IntuitionBase *IntuitionBase;

struct NewMenu mynewmenu[] =
    {
        { NM_TITLE, "Project",    0 , 0, 0, 0,},
        {  NM_ITEM, "Open...",   "O", 0, 0, 0,},
        {  NM_ITEM, "Save",      "S", 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Print",      0 , 0, 0, 0,},
        {   NM_SUB, "Draft",      0 , 0, 0, 0,},
        {   NM_SUB, "NLQ",        0 , 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Quit...",   "Q", 0, 0, 0,},

        { NM_TITLE, "Edit",       0 , 0, 0, 0,},
        {  NM_ITEM, "Cut",       "X", 0, 0, 0,},
        {  NM_ITEM, "Copy",      "C", 0, 0, 0,},
        {  NM_ITEM, "Paste",     "V", 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Undo",      "Z", 0, 0, 0,},

        {   NM_END, NULL,         0 , 0, 0, 0,},
    };

/* Watch the menus and wait for the user to select the close gadget or quit from the menus. */
VOID handle_window_events(struct Window *win, struct Menu *menuStrip)
{
struct IntuiMessage *msg;
SHORT done;
UWORD menuNumber;
UWORD menuNum;
UWORD itemNum;
UWORD subNum;
struct MenuItem *item;

done = FALSE;
while (FALSE == done)
    {
    /* we only have one signal bit, so we do not have to check which
    ** bit broke the Wait().
    */
    Wait(1L << win->UserPort->mp_SigBit);

    while ( (FALSE == done) &&
            (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort))))
        {
        switch (msg->Class)
            {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            case IDCMP_MENUPICK:
                menuNumber = msg->Code;
                while ((menuNumber != MENUNULL) && (!done))
                    {
                    item = ItemAddress(menuStrip, menuNumber);

                    /* process the item here! */
                    menuNum = MENUNUM(menuNumber);
                    itemNum = ITEMNUM(menuNumber);
                    subNum  = SUBNUM(menuNumber);

                    /* stop if quit is selected. */
                    if ((menuNum == 0) && (itemNum == 5))
                        done = TRUE;

                    menuNumber = item->NextSelect;
                    }
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}

/*
** Open all of the required libraries and set-up the menus.
*/
VOID main(int argc, char *argv[])
{
struct Window *win;
APTR *my_VisualInfo;
struct Menu *menuStrip;

/* Open the Intuition Library */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37);
if (IntuitionBase != NULL)
    {
    /* Open the gadtools Library */
    GadToolsBase = OpenLibrary("gadtools.library", 37);
    if (GadToolsBase != NULL)
        {
        if (NULL != (win = OpenWindowTags(NULL,
                            WA_Width,  400,       WA_Activate,    TRUE,
                            WA_Height, 100,       WA_CloseGadget, TRUE,
                            WA_Title,  "Menu Test Window",
                            WA_IDCMP,  IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,
                            TAG_END)))
            {
            if (NULL != (my_VisualInfo = GetVisualInfo(win->WScreen, TAG_END)))
                {
                if (NULL != (menuStrip = CreateMenus(mynewmenu, TAG_END)))
                    {
                    if (LayoutMenus(menuStrip, my_VisualInfo, TAG_END))
                        {
                        if (SetMenuStrip(win, menuStrip))
                            {
                            handle_window_events(win,menuStrip);

                            ClearMenuStrip(win);
                            }
                        FreeMenus(menuStrip);
                        }
                    }
                FreeVisualInfo(my_VisualInfo);
                }
            CloseWindow(win);
            }
        CloseLibrary((struct Library *)GadToolsBase);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}
Coder's Clinic 3



   CCCC    OOOO   DDDD   EEEEEE    CCCC  L      IIIII N    N IIIII  CCCC
  C    C  O    O  D   D  E        C    C L        I   NN   N   I   C    C
 C       O      O D    D EEE     C       L        I   N NN N   I  C
  C    C  O    O  D   D  E        C    C L        I   N   NN   I   C    C
   CCCC    OOOO   DDDD   EEEEEE    CCCC  LLLLLL IIIII N    N IIIII  CCCC
--------------------------------------------------------------------------
CODE CLINIC #3                                        I LUV GADGETS!!!  


        As promised, We will add a gadget to our window. First we have to
        get some info on how to do this.

        GADGETS:Two types of gadgets.

        *FIRST TYPE OF GADGET:System                 
        System gadgets are those that you see in the windows and screens
        that you open. And we are  not going to go much further than that.
        
        *SECOND TYPE OF GADGET:Application
        Application gadgets are the ones in which you create and 
                use in your own programs. They can be placed at any 
                location inside the window and can use any image. 
                There are four basic types of application gadgets.

        [1] Boolean    : OK buttons ect...                 
        [2] Proportion : Sound level ect...
        [3] String     : Enter your name ect...                 
        [4] Custom     : New gadgets.
        
       
      *****--------------------------------------------------       
      * N *   I STRONGLY SUGGEST INVESTING IN THE COMPLETE  |
      * O *   SET OF AMIGA ROM KERNEL MANUALS... AT THE     |
      * T *   VERY LEAST YOU SHOULD TRY TO GET THE LIBRARIES|       
      * E *   MANUAL ...THERE ARE MANY EXAMPLES/EXPLANATIONS|       
      *****--------------------------------------------------
                 To create a gadget you simply fill in a Gadget structure. 
        (see fig.�1). You may also use the Gadtools Library to create 
        gadgets (which we will), As you can see the Gadget structure has 
        many items 
        and to cover all these would     struct Gadget                   
        consume a great deal of text    {                                
        as suggested before get the        struct Gadget *NextGadget     
        ROM Kernel manual:Libraries        WORD LeftEdge, TopEdge;       
        (at the very least) as there       WORD Width, Height;           
        is detailed information on all     UWORD Flags;                  
        structures the amiga programmer    UWORD Activation;             
        needs to understand.               UWORD GadgetType;             
                                           APTR GadgetRender;            
        OK lets do something different     APTR SelectRender;            
        like use the Gadtools Library      struct IntuiText *GadgetText; 
        to put some gadgets up on the      LONG MutualExclude;           
        window and let us know which one   APTR SpecialInfo;             
        we selected.                       UWORD GadgetID;               
                                           APTR UserData;                
        Now that we know about the       };                              
        Intuistion gadgets lets take a               FIG. 1              
        look at the Gadtools gadgets.
        
        There are 12 types of gadgets that the Gadtools library supports
        and they are:
        
       Button                 
       String             
       Integer            
       Checkboxes              
       Mutually exclusive 
       Cycle              
       Sliders            
       Scrollers          
       Listviews          
       Palette            
       Text-display       
       Numeric-display    
       
       With all of these types of gads what couldnt you do? And as a real
       bonus there are several GUI buiders on aminet, just look in dev/gui
       and you will see several I personally like GadToolBox by Jan van den
       Baard. These programs take a great deal of coding off of your back 
       and allow you to work on the inner workings of your own program.
       
       Lets take a look a the structure used to create a gadtools gadget:
       
                struct NewGadget                       
                {                                      
                        WORD ng_LeftEdge,ng_TopEdge;  
                        WORD ng_Width,ng_Height;      
                        UBYTE *ng_GadgetText;         
                        struct TextAttr *ng_TextAttr; 
                        UWORD ng_GadgetID;             
                        ULONG ng_Flags;                
                        APTR  ng_VisualInfo;           
                        APTR  ng_UserData;             
                };                                     
                               FIG 2                 
                
                If you compare the Gadget (fig 1) and the NewGadget (fig 2)
        structures you will see some common items.
       
       The way you create a gadget using gadtools is the CreateGadget()
       function, its prototype is:
        
        struct Gadget *CreateGadget(ULONG kind,
                                    struct Gadget *prevgad,
                                    struct NewGadget *newgad,
                                    struct TagItem *taglist);
       so to create a single button gadget we would do it like this:
       
       ng.ng_TextAttr   = &Topaz80;
       ng,ng_VisualInfo = vi;
       ng.ng_LeftEdge   = 10;
       ng.ng_TopEdge    = 10;
       ng.ng_Width      = 60;
       ng.ng_Height     = 12;
       ng.ng_GadgetText = "CLICK";
       ng.ng_GadgetID   = 1;
       ng.ng_Flags      = 0;
       gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);
                                            _____________________________
       If you look at fig 2 you will        []hello__________________[][]
       see that we have filled the          |                           |
       structure and then made a call       |  CLICK  QUIT            |
       to CreateGadget(). The nice          |                           |
       thing is that if you were to         |                           | 
       add another gadget you now only      |                           |
       fill in the items that will          |                           |
       change, an example of this           |                           |
       is given below. Lets add a           |___________________________|
       gadget that has "QUIT" inside                     
       it.                                             FIG 4             
       
       ng.LeftEdge      =80;
       ng.ng_GadgetText ="QUIT";
       ng.ng_GadgetID   =2;
       gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

       and now we would have two gadgets that would look like fig�4
       
       
       The example program was created using the example from the ROM 
       Kernel Manual:Libraries in the chapter Gadtools Library pg.383-385.
       
       I would also like to mention that this layout was written by me and 
       not by a GUI builder... and this is the GUI that we will use to 
       create our AddressBook program.
       
       There are several new items to this code and alot of it you will not
       understand, I will try to clear up any questions in the next issue
       as we will go line by line of this code and explain what is going
       on... 
       
      *****-------------------------  *****-------------------------       
      * N *   ALL CODE IS INTENDED |  * N *   I COMPILED THIS CODE |
      * O *   FOR VERSION 2.0 OR   |  * O *   WITH SAS/C V6.0 AND  |
      * T *   ABOVE...             |  * T *   HAD NO ERRORS OR     |       
      * E *                        |  * E *   WARNINGS             |       
      *****-------------------------  *****-------------------------

//.C..C.O.D.E..............................................................

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <stdio.h>



VOID process_window_events(struct Window *);  VOID gadtoolsWindow(VOID);
VOID Do_Gad(struct Window *mywin,struct Gadget *gad,UWORD code);  BOOL
terminated = FALSE;  struct TextAttr Topaz80 = { "topaz.font",8,0,0,};

struct Library *IntuitionBase; struct Library *GadToolsBase;

void main(void) {
        if ((IntuitionBase = OpenLibrary("intuition.library",37))!=NULL)
           {
           if ((GadToolsBase = OpenLibrary("gadtools.library",37))!=NULL)
              {
              gadtoolsWindow();
              
              CloseLibrary(GadToolsBase);
              }
           CloseLibrary(IntuitionBase);
           } }

VOID gadtoolsWindow(VOID) { struct Screen *mysc; struct Window *mywin;
struct Gadget *glist, *gad; struct NewGadget ng; void   *vi;

glist = NULL;

if ((mysc = LockPubScreen(NULL)) != NULL)
   {
   if ((vi = GetVisualInfo(mysc, TAG_END)) != NULL)
      {
      gad = CreateContext(&glist);
      
      ng.ng_TextAttr    =&Topaz80;
      ng.ng_VisualInfo  =vi;
      
      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     =2+mysc->WBorTop+(mysc->Font->ta_YSize+1);
      ng.ng_Width       =16;
      ng.ng_Height      =12;
      ng.ng_GadgetText  ="A";
      ng.ng_GadgetID    =1;
      ng.ng_Flags       =0;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="B";
      ng.ng_GadgetID    =2;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="C";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="D";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);      

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="E";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     +=14;
      ng.ng_GadgetText  ="F";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="G";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="H";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="I";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="J";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     +=14;
      ng.ng_GadgetText  ="K";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="L";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="M";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="N";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="O";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     +=14;
      ng.ng_GadgetText  ="P";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="Q";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="R";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="S";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="T";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     +=14;
      ng.ng_GadgetText  ="U";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="V";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="W";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="X";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    +=18 ;
      ng.ng_GadgetText  ="Y";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge    =300;
      ng.ng_TopEdge     +=14;
      ng.ng_GadgetText  ="Z";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);

      ng.ng_LeftEdge     +=18;
      ng.ng_GadgetText  ="?";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);


      ng.ng_LeftEdge    +=18 ;
      ng.ng_Width       =54;
      ng.ng_GadgetText  ="ADD";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);      

      ng.ng_TopEdge    +=14;
      ng.ng_Width       =54;
      ng.ng_GadgetText  ="QUIT";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);    

      ng.ng_LeftEdge    =10;
      ng.ng_TopEdge     =2+mysc->WBorTop+(mysc->Font->ta_YSize+1);
      ng.ng_Width       =180;
      ng.ng_Height       =12;
      ng.ng_GadgetText  ="BOOL 1";
      ng.ng_GadgetID    ++;
      gad= CreateGadget(BUTTON_KIND,gad,&ng,TAG_END);




      if (gad != NULL)
         {
         if ((mywin = OpenWindowTags(NULL,
                WA_Title,  "PhoneBook V1.0",
                WA_Gadgets, glist,      WA_AutoAdjust, TRUE,
                WA_Width, 400,          WA_InnerHeight, 100,
                WA_DragBar, TRUE,       WA_DepthGadget, TRUE,
                WA_Activate, TRUE,      WA_CloseGadget, TRUE,
                WA_IDCMP, IDCMP_CLOSEWINDOW | 
                          IDCMP_REFRESHWINDOW | 
                          BUTTONIDCMP,
                WA_PubScreen, mysc,
                TAG_END)) != NULL)
                  {
                  GT_RefreshWindow(mywin,NULL);
                  
                  process_window_events(mywin);
                  
                  CloseWindow(mywin);
                  
                  }
         }
        FreeGadgets(glist);
        FreeVisualInfo(vi);
        }
      UnlockPubScreen(NULL,mysc);
      } }

VOID process_window_events(struct Window *mywin) { struct IntuiMessage
*imsg; ULONG  class; UWORD  code; struct Gadget *gad;


while (!terminated)
        {
        Wait(1<< mywin->UserPort->mp_SigBit);
        while ((!terminated) && (imsg = GT_GetIMsg(mywin->UserPort)))
           {
           gad = (struct Gadget *)imsg->IAddress;
           class=imsg->Class;
           code =imsg->Code;
           
           switch (class)
              {
              case IDCMP_GADGETUP:
                                  Do_Gad(mywin,gad,code);
                                  break;
      
              case IDCMP_CLOSEWINDOW:
                                  terminated = TRUE;
                                  break;
              case IDCMP_REFRESHWINDOW:
                                  GT_BeginRefresh(mywin);
                                  GT_EndRefresh(mywin,TRUE);
                                  break;
              }
              GT_ReplyIMsg(imsg);
       }
   } } VOID Do_Gad(struct Window *mywin,struct Gadget *gad,UWORD code) {
switch(gad->GadgetID)
        {
        case 1:printf("A\n");
               break;
        case 2:printf("B\n");
               break;
        case 3:printf("C\n");
               break;
        case 4:printf("D\n");
               break;
        case 5:printf("E\n");
               break;
        case 6:printf("F\n");
               break;
        case 7:printf("G\n");
               break;
        case 8:printf("H\n");
               break;
        case 9:printf("I\n");
               break;
        case 10:printf("J\n");
               break;
        case 11:printf("K\n");
               break;
        case 12:printf("L\n");
               break;
        case 13:printf("M\n");
               break;
        case 14:printf("N\n");
               break;
        case 15:printf("O\n");
               break;
        case 16:printf("P\n");
               break;
        case 17:printf("Q\n");
               break;
        case 18:printf("R\n");
               break;
        case 19:printf("S\n");
               break;
        case 20:printf("T\n");
               break;
        case 21:printf("U\n");
               break;
        case 22:printf("V\n");
               break;
        case 23:printf("W\n");
               break;
        case 24:printf("X\n");
               break;
        case 25:printf("Y\n");
               break;
        case 26:printf("Z\n");
               break;
        case 29:printf("TERMINATE\n");
                terminated = TRUE;
                break;
        }  }


// End C Code

参考文献

[编辑 | 编辑源代码]

某些代码依赖于使用伪造(非 boopsi)组件的 gadtools 库的 AOS 实现,其中尤其是在更复杂的组件(列表视图)中,大多数组件(输入)处理都在 GT_GetImsg/GT_FitlerImsg() 函数中完成。在 AROS gadtools 库中使用真正的 boopsi 组件,因此行为有所不同。

struct Gadget *CreateGadgetA(ULONG kind, struct Gadget *previous, struct NewGadget *ng, struct TagItem *taglist) 
void FreeGadgets(struct Gadget *glist)
void GT_SetGadgetAttrsA(struct Gadget *gad, struct Window *win, struct Requester *req, struct TagItem *tagList) 
struct Menu *CreateMenusA(struct NewMenu *newmenu, struct TagItem *tagList) 
void FreeMenus(struct Menu *menu) 
BOOL LayoutMenuItemsA(struct MenuItem *menuitem, APTR vi, struct TagItem *tagList) 
BOOL LayoutMenusA(struct Menu *menu, APTR vi, struct TagItem *tagList) 
struct IntuiMessage *GT_GetIMsg(struct MsgPort *intuiport) 
void GT_ReplyIMsg(struct IntuiMessage *imsg) 
void GT_RefreshWindow(struct Window *win, struct Requester *req) 
void GT_BeginRefresh(struct Window *win) 
void GT_EndRefresh(struct Window *win, BOOL complete) 
struct IntuiMessage *GT_FilterIMsg(struct IntuiMessage *imsg)
struct IntuiMessage *GT_PostFilterIMsg(struct IntuiMessage *modimsg) 
struct Gadget *CreateContext(struct Gadget **glistpointer) 
void DrawBevelBoxA(struct RastPort *rport, WORD left, WORD top, WORD width, WORD height, struct TagItem *taglist) 
APTR GetVisualInfoA(struct Screen *screen, struct TagItem *tagList) 
void FreeVisualInfo(APTR vi)

LONG GT_GetGadgetAttrsA(struct Gadget *gad, struct Window *win, struct Requester *req, struct TagItem *taglist) 

每个选项中的前几个项目可以在创建后进行更改。

GA_Immediate 和 GA_RelVerify 是标签,GACT_IMMEDIATE 和 GACT_RELVERIFY 是用于 struct Gadget 的 Activation 字段的标志。

CreateGadgetA Taglists

GT_Underscore - 指示在要加下划线的组件标签中字符之前的符号。这可以用来指示组件的键盘等效项(请注意,GadTools 不会处理键 - 只显示下划线)。

BUTTON_OPTION(操作按钮)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE).

GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from button gadget (default FALSE). 

CHECKBOX_OPTION(开/关项目)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE).
GTCB_Checked (BOOL) - Initial state of checkbox (default FALSE)

GTCB_Scaled (BOOL) - If true, then checkbox imagery will be scaled to fit the gadget's width & height.  Otherwise, a fixed size of CHECKBOXWIDTH by CHECKBOXHEIGHT will be used. (default FALSE)

CYCLEOPTION(多状态选择)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTCY_Labels (STRPTR *) - Pointer to NULL-terminated array of strings that are the choices offered by the cycle gadget. This tag is required. 
GTCY_Active (UWORD) - The ordinal number (counting from zero) of the initially active choice of a cycle gadget (default zero).

INTEGER_OPTION(数字输入)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTIN_Number (LONG) - The initial contents of the integer gadget (default 0).

GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from integer gadget (default FALSE). 
GA_TabCycle (BOOL) - Set to TRUE so that pressing  or will activate the next or previous such gadget. (default TRUE).
GTIN_MaxChars (UWORD) - The maximum number of digits that the integer gadget is to hold (defaults to 10). 
GTIN_EditHook (struct Hook *) - Hook to use as a custom integer gadget edit hook (StringExtend->EditHook) for this gadget. GadTools will allocate the StringExtend->WorkBuffer for you. (default NULL). 
STRINGA_ExitHelp (BOOL) - Set to TRUE to have the help-key cause an exit from the integer gadget.  You will then receive an IDCMP_GADGETUP event with Code = 0x5F (rawkey for help). (default FALSE) 
STRINGA_Justification - Controls the justification of the contents of an integer gadget.  Choose one of STRINGLEFT, STRINGRIGHT, or STRINGCENTER (defaults to STRINGLEFT). 
STRINGA_ReplaceMode (BOOL) - If TRUE, this integer gadget is in replace-mode (default FALSE (insert-mode)). 

LISTVIEW_OPTION(滚动列表)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTLV_Top (WORD) - Top item visible in the listview.  This value will be made reasonable if out-of-range (default 0). 
GTLV_Labels (struct List *) - List of nodes whose ln_Name fields are to be displayed in the listview. 
GTLV_Selected (UWORD) - Ordinal number of currently selected item, or 0 to have no current selection (default 0).

GTLV_MakeVisible (WORD) - Number of an item that should be forced within the visible area of the listview by doing minimal scrolling. This tag overrides GTLV_Top. 
GTLV_ReadOnly (BOOL) - If TRUE, then listview is read-only (default FALSE). 
GTLV_ScrollWidth (UWORD) - Width of scroll bar for listview. Must be greater than zero (default 16). 
GTLV_ShowSelected (struct Gadget *) - NULL to have the currently selected item displayed beneath the listview under V37 or with a highlight bar in V39. If not NULL, this is a pointer to an already-created GadTools STRING_KIND gadget to have an editable display of the currently selected item. If the tag is not present, the currently selected item will not be displayed. 
LAYOUTA_Spacing (UWORD) - Extra space to place between lines of listview (default 0). 
GTLV_ItemHeight (UWORD) - The exact height of an item. This is normally useful for listviews that use the GTLV_CallBack 	    rendering hook (defaults to ng->ng_TextAttr->ta_YSize). 
GTLV_CallBack (struct Hook *) - Callback hook for various listview operations. Only callback supported is for custom rendering of individual items in the listview. The call back hook is called with:
		A0 - struct Hook *
		A1 - struct LVDrawMsg *
		A2 - struct Node *
The callback hook *must* check the lvdm_MethodID field of the message and only do processing if it equals LV_DRAW. If any other value is passed, the callback hook must return LVCB_UNKNOWN 
GTLV_MaxPen (UWORD) - The maximum pen number used by rendering in a custom rendering callback hook. This is used to optimize the rendering and scrolling of the listview display (default being the maximum pen number used by all of TEXTPEN, BACKGROUNDPEN, FILLPEN, TEXTFILLPEN, and BLOCKPEN. 

MX_OPTION(互斥,单选按钮)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE).
GTMX_Active (UWORD) - The ordinal number (counting from zero) of the initially active choice of an mx gadget (default 0).

GTMX_Labels (STRPTR *) - Pointer to a NULL-terminated array of strings which are to be the labels beside each choice in a set of mutually exclusive gadgets. This tag is required 
GTMX_Spacing (UWORD) - The amount of space between each choice of a set of mutually exclusive gadgets.  This amount is added  to the font height to produce the vertical shift between choices (default 1). 
GTMX_Scaled (BOOL) - If true, then mx gadget imagery will be scaled to fit the gadget's width & height.  Otherwise, a fixed size of MXWIDTH by MXHEIGHT will be used. When setting this tag to TRUE, should typically set the height of the gadget to be (ng.ng_TextAttr->ta_YSize + 1). (default FALSE.) 
GTMX_TitlePlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT, PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the title of the gadget is to be displayed. Without this tag, the NewGadget.ng_GadgetText field is ignored for MX_OPTION gadgets.

LAYOUTA_Spacing - FOR COMPATIBILITY ONLY.  Use GTMX_Spacing instead. The number of extra pixels to insert between each choice of a mutually exclusive gadget.  This is added to the present gadget image height (9) to produce the true spacing between choices. (default FontHeight-8, which is zero for 8-point font users). 

NUMBER_OPTION(只读数字)

GTNM_Number (LONG) - A signed long integer to be displayed as a read-only number (default 0).

GTNM_Border (BOOL) - If TRUE, this flag asks for a recessed border to be placed around the gadget. 
GTNM_FrontPen (UBYTE) - The pen to use when rendering the number (default DrawInfo->dri_Pens[TEXTPEN]). 
GTNM_BackPen (UBYTE) - The pen to use when rendering the background of the number (defaults to leaving the background untouched). 
GTNM_Justification (UBYTE) - Determines how the number is rendered within the gadget box. GTJ_LEFT will make the rendering be flush with the left side of the gadget, GTJ_RIGHT will make it flush with the right side, and GTJ_CENTER will center the number within the gadget box. (default GTJ_LEFT). 
GTNM_Format (STRPTR) - C-Style formatting string to apply on the number before display. Be sure to use the 'l' (long) modifier. This string is processed using exec.library/RawDoFmt(), so refer to that function for details. (default "%ld") 
GTNM_MaxNumberLen (ULONG) - Maximum number of bytes that can be generated by applying the GTNM_Format formatting string to the number (excluding the NULL terminator). (default 10). 
GTNM_Clipped (BOOL) - Determine whether text should be clipped to the gadget dimensions (defaults to FALSE for gadgets without borders, TRUE for gadgets with borders). 

PALETTE_OPTION(颜色选择)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTPA_Color (UBYTE) - Initially selected color of the palette. This number is a pen number, and not the ordinal color number within the palette gadget itself. (default 1). 
GTPA_ColorOffset (UBYTE) - First color to use in palette (default 0).
GTPA_ColorTable (UBYTE *) - Pointer to a table of pen numbers indicating  which colors should be used and edited by the palette gadget. This array must contain as many entries as there are colors displayed in the palette gadget. The array provided with this tag must remain valid for the life of the gadget or until a new table is provided. (default NULL, which causes a 1-to-1 mapping of pen numbers).

GTPA_Depth (UWORD) - Number of bitplanes in the palette (default 1). 
GTPA_IndicatorWidth (UWORD) - The desired width of the current-color indicator, if you want one to the left of the palette. 
GTPA_IndicatorHeight (UWORD) - The desired height of the current-color indicator, if you want one above the palette. 
GTPA_NumColors (UWORD) - Number of colors to display in the palette gadget. This override GTPA_Depth and allows numbers which are not powers of 2. (default 2) 

SCROLLER_OPTION(用于在区域或列表中滚动)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTSC_Top (WORD) - Top visible in area scroller represents (default 0). 
GTSC_Total (WORD) - Total in area scroller represents (default 0). 
GTSC_Visible (WORD) - Number visible in scroller (default 2).

GA_RelVerify (BOOL) - Hear every IDCMP_GADGETUP event from scroller (default FALSE). 
GA_Immediate (BOOL) - Hear every IDCMP_GADGETDOWN event from scroller (default FALSE). 
GTSC_Arrows (UWORD) - Asks for arrows to be attached to the scroller. The value supplied will be taken as the width of each arrow button for a horizontal scroller, or the height of each button for a vertical scroller (the other dimension will match the whole scroller).

PGA_Freedom - Whether scroller is horizontal or vertical. Choose LORIENT_VERT or LORIENT_HORIZ (default LORIENT_HORIZ).

SLIDER_OPTION(指示级别或强度)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTSL_Min (WORD) - Minimum level for slider (default 0).  
GTSL_Max (WORD) - Maximum level for slider (default 15). 
GTSL_Level (WORD) - Current level of slider (default 0).

GA_RelVerify (BOOL) - If you want to hear each slider IDCMP_GADGETUP event (default FALSE). 
GA_Immediate (BOOL) - If you want to hear each slider IDCMP_GADGETDOWN event (default FALSE). 
GTSL_MaxLevelLen (UWORD) - Maximum length in characters of level string when rendered beside slider (default 2). 
GTSL_LevelFormat (STRPTR) - C-Style formatting string for slider level.  Be sure to use the 'l' (long)  modifier.  This string is processed using exec.library/RawDoFmt(), so refer to that function for details. (default "%ld"). 
GTSL_LevelPlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT, PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the level indicator is to go relative to slider (default to PLACETEXT_LEFT). 
GTSL_DispFunc ( LONG (*function)(struct Gadget *, WORD) ) - To calculate level to be displayed.  A number-of-colors slider might want to set the slider up to think depth, and have a (1 << n) function here. No Default  Your function must take a pointer to gadget as the first parameter, the level (a WORD) as the second, and return the result as a LONG. 
GTSL_MaxPixelLen (ULONG) - Indicates the maximum pixel size used up by the level display for any value of the slider. This is mostly useful when dealing with proportional fonts. (default FontWidth*MaxLevelLen). 
GTSL_Justification (UBYTE) - Determines how the level display is to be justified within its alotted space. Choose one of GTJ_LEFT, GTJ_RIGHT, or GTJ_CENTER (default GTJ_LEFT).

PGA_Freedom - Set to LORIENT_VERT or LORIENT_HORIZ to have a vertical or horizontal slider (defaults to LORIENT_HORIZ). 

STRING_OPTION(文本输入)

GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise (default FALSE). 
GTST_String (STRPTR) - The initial contents of the string gadget, or NULL (default) if string is to start empty. 
GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from string gadget (default FALSE). 
GA_TabCycle (BOOL) - Set to TRUE so that pressing  or will activate the next or previous such gadget. (defaults to TRUE, unlike regular Intuition string gadgets which default FALSE).
GTST_MaxChars (UWORD) - The maximum number of characters that the string gadget is to hold. 
GTST_EditHook (struct Hook *) - Hook to use as a custom string gadget edit hook (StringExtend->EditHook) for this gadget. GadTools will allocate the StringExtend->WorkBuffer for you. (default NULL).
STRINGA_ExitHelp (BOOL) - Set to TRUE to have the help-key cause an exit from the string gadget.  You will then receive an IDCMP_GADGETUP event with Code = 0x5F (rawkey for help).
STRINGA_Justification - Controls the justification of the contents of a string gadget.  Choose one of STRINGLEFT, STRINGRIGHT, or STRINGCENTER (default STRINGLEFT). 
STRINGA_ReplaceMode (BOOL) - If TRUE, this string gadget is in replace-mode (defaults to FALSE (insert-mode)). 

TEXT_OPTION(只读文本)

GTTX_Text - Pointer to a NULL terminated string to be displayed, as a read-only text-display gadget, or NULL. (default NULL)

GTTX_CopyText (BOOL) -	This flag instructs the text-display gadget to copy the supplied text string, instead of using only pointer to the string.  This only works for the initial value of GTTX_Text set at CreateGadget() time.  If you subsequently change GTTX_Text, the new text will be referenced by pointer, not copied.  Do not use this tag with a NULL GTTX_Text. 
GTTX_Border (BOOL) - If TRUE, this flag asks for a recessed border to be placed around the gadget. 
GTTX_FrontPen (UBYTE) - The pen to use when rendering the text (default DrawInfo->dri_Pens[TEXTPEN]). 
GTTX_BackPen (UBYTE) - The pen to use when rendering the background of the text (defaults to leaving the background untouched).
GTTX_Justification (UBYTE) - Determines how the text is rendered within the gadget box. GTJ_LEFT will make the rendering be flush with the left side of the gadget, GTJ_RIGHT will make it flush with the right side, and GTJ_CENTER will center the text within the gadget box. (default GTJ_LEFT).
GTTX_Clipped (BOOL) - Determine whether text should be clipped to the gadget dimensions (defaults to FALSE for gadgets without borders, TRUE for gadgets with borders). 

LayoutGadgetTags

GTMN_Menu (struct Menu *) - Pointer to the Menu structure whose FirstItem is the MenuItem supplied. If the menu items are such that they need to be columnized or shifted, the Menu structure is needed to perform the complete calculation. For the following tags, please see the description under LayoutMenusA().  Their behavior is identical when used in LayoutMenuItemsA(). 
	    GTMN_TextAttr
	    GTMN_NewLookMenus
	    GTMN_Checkmark
	    GTMN_AmigaKey
	    GTMN_FrontPen

尝试在控制台代码(用于菜单)中手动打开 gadtools。我需要手动打开它,因为它*将*在引导外壳中失败(见下文),因此我需要处理它不可用的情况。在我看来,在引导期间自动打开非驻留库是一个非常糟糕的主意……如果关闭它,很多东西都会坏掉吗?或者,是否存在一种方法可以逐个案例地防止自动打开?据我所知,您只需要手动声明基本指针。这将阻止从 libautoinit 获取它(以及相关的库打开代码)。对于程序,它有效。我认为它对驻留程序有效。autoinit 代码由 libbase 变量链接。例如,autoinit 代码定义了库的全局 libbase 变量。如果在代码中的某个地方将“struct Library *GadToolsBase”定义为全局变量,则不会链接 autoinit 代码。请仅在确实需要时使用它,并添加适当的注释说明为什么需要它。此处的具体情况是避免在控制台代码中复制大量来自 gadtools 的菜单布局代码,以将菜单添加到控制台窗口,而无需将 gadtools 链接到内核。这意味着引导外壳将无法获得菜单,但我认为与使事情变得非常混乱相比,这是一个相当公平的权衡。

而且它只在全局库基址被使用时才会被调用,对于可移动代码来说不应该如此,是吗?这是我没有考虑到的。如果我声明一个全局 GadToolsBase,我是否会弄乱一些东西,或者 bss 是否被正确处理?如果它弄乱了事情,是否有其他方法可以防止自动打开?(提交了控制台处理程序的基本菜单结构,该结构使用全局 GadToolsBase)。

实际上,它不是最佳的,因为在 m68k 上,.bss 的唯一“已知始终存在”的内存位于芯片 RAM 中,芯片 RAM 既宝贵又慢(由于与视频和音频操作的争用)。对于此用法,它可能没问题,但如果您能找到一种方法将其分配到控制台处理程序传递的结构(con_base?)中并从那里取消引用它,这可能是一种更好的方法。AllocMem() 内存从最高优先级开始分配。请参阅 rom/devs/filesys/AmberRAM/handler.h 的“struct Handler”,以及紧随其后的宏,了解如何执行此操作的示例。控制台处理程序已经在其处理程序数据结构中放置了许多内容,因此如果有一种方法可以抑制自动打开而无需使用全局变量,那么将其放在那里非常简单。

在 NEWWINDOWSIZE 事件期间,是否有某个地方提供关于所有需要处理事项的良好参考?你可能已经知道,但与 SIZEVERIFY 不同,NEWWINDOWSIZE 不会像 ReplyMsg() 一样阻塞。

字节序问题

代码中可能存在方法结构体,它使用 WORD 作为某些(坐标)字段,然后在调用该方法时执行类似 gDoClassMethod(... , (x << 16) | (y & 0xffff), ...)。这依赖于大端字节序,因此在 x86 上会失败。

华夏公益教科书