home *** CD-ROM | disk | FTP | other *** search
Wrap
/* GadTools layout toolkit ** ** Copyright © 1993-1994 by Olaf `Olsen' Barthel ** Freely distributable. */ #include <exec/execbase.h> #include <exec/memory.h> #include <graphics/videocontrol.h> #include <graphics/gfxmacros.h> #include <graphics/gfxbase.h> #include <intuition/intuitionbase.h> #include <intuition/gadgetclass.h> #include <intuition/imageclass.h> #include <intuition/classusr.h> #include <intuition/icclass.h> #include <intuition/screens.h> #include <intuition/classes.h> #include <intuition/sghooks.h> #include <libraries/gadtools.h> #include <libraries/locale.h> #include <devices/timer.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <dos.h> #include <clib/intuition_protos.h> #include <clib/graphics_protos.h> #include <clib/gadtools_protos.h> #include <clib/diskfont_protos.h> #include <clib/utility_protos.h> #include <clib/keymap_protos.h> #include <clib/locale_protos.h> #include <clib/exec_protos.h> #include <clib/macros.h> #include <pragmas/intuition_pragmas.h> #include <pragmas/graphics_pragmas.h> #include <pragmas/gadtools_pragmas.h> #include <pragmas/diskfont_pragmas.h> #include <pragmas/utility_pragmas.h> #include <pragmas/keymap_pragmas.h> #include <pragmas/locale_pragmas.h> #include <pragmas/exec_pragmas.h> #define _GTLAYOUT_C #include "gtlayout.h" /*****************************************************************************/ // Keyboard qualifiers #define QUALIFIER_SHIFT (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) #define QUALIFIER_ALT (IEQUALIFIER_LALT | IEQUALIFIER_RALT) #define QUALIFIER_CONTROL (IEQUALIFIER_CONTROL) /*****************************************************************************/ // Undefine these to remove various chunks of support from this code #ifdef LIB_CODE #define DO_PASSWORD_KIND #define DO_FRACTION_KIND #define DO_GAUGE_KIND #define DO_TAPEDECK_KIND #define DO_HEXHOOK #define DO_PICKSHORTCUTS #define DO_CLONING #else #define DO_PASSWORD_KIND //#define DO_FRACTION_KIND #define DO_GAUGE_KIND //#define DO_HEXHOOK #define DO_PICKSHORTCUTS #define DO_CLONING #define DO_TAPEDECK_KIND #endif /* LIB_CODE */ /*****************************************************************************/ // Stuff from amiga.lib that we want to declare stdargs/regargs VOID __regargs NewList(struct MinList *list); VOID __regargs TimeDelay(LONG unit,ULONG secs,ULONG micros); ULONG __regargs DoSuperMethodA(struct IClass *cl, Object *obj, Msg message); APTR __asm AsmCreatePool(register __d0 ULONG MemFlags,register __d1 ULONG PuddleSize,register __d2 ULONG ThreshSize,register __a6 struct ExecBase *SysBase); VOID __asm AsmDeletePool(register __a0 APTR PoolHeader,register __a6 struct ExecBase *SysBase); APTR __asm AsmAllocPooled(register __a0 APTR PoolHeader, register __d0 ULONG Size,register __a6 struct ExecBase *SysBase); VOID __asm AsmFreePooled(register __a0 APTR PoolHeader,register __a1 APTR Memory,register __d0 ULONG MemSize,register __a6 struct ExecBase *SysBase); VOID __stdargs kprintf(STRPTR,...); /*****************************************************************************/ // Scan an Exec list #define SCANLIST(l,n) for(n = (APTR)((struct MinList *)l) -> mlh_Head; \ ((struct MinNode *)n) -> mln_Succ; \ n = (APTR)((struct MinNode *)n) -> mln_Succ) // Scan the objects of a group #define SCANGROUP(g,n) for(n = (APTR)g -> Special . Group . ObjectList . mlh_Head; \ ((struct MinNode *)n) -> mln_Succ; \ n = (APTR)((struct MinNode *)n) -> mln_Succ) // Scan the objects of a group, only allowing active pages #define SCANPAGE(g,n,p) for(p = 0, n = (APTR)g -> Special . Group . ObjectList . mlh_Head; \ ((struct MinNode *)n) -> mln_Succ; \ n = (APTR)((struct MinNode *)n) -> mln_Succ) \ if ((p++ == g -> Special . Group . ActivePage) || !g -> Special . Group . Paging) // Get an object pointer from a gadget pointer #define GETOBJECT(g,n) ((n = (ObjectNode *)g -> UserData) && (n -> Host == g) && (n -> PointBack == n)) /*****************************************************************************/ #ifdef DO_PASSWORD_KIND #define TEST_PASSWORD_KIND(n) || (n -> Type == PASSWORD_KIND) #else #define TEST_PASSWORD_KIND(n) || (FALSE) #endif #ifdef DO_FRACTION_KIND #define TEST_FRACTION_KIND(n) || (n -> Type == FRACTION_KIND) #else #define TEST_FRACTION_KIND(n) || (FALSE) #endif // Is an object derived from STRING_KIND? #define LIKE_STRING_KIND(n) ((n -> Type == STRING_KIND) TEST_PASSWORD_KIND(n) TEST_FRACTION_KIND(n)) /*****************************************************************************/ typedef UBYTE BOOLEAN; #define INCREMENTER_KIND 42 #define PICKER_KIND 43 #define GROUP_KIND 44 typedef struct GaugeExtra { LONG InfoLength; STRPTR InfoText; } GaugeExtra; typedef struct TapeDeckExtra { struct Image *ButtonImage; LONG ButtonWidth, ButtonHeight; BOOLEAN ButtonType, Toggle, Pressed, Smaller; } TapeDeckExtra; typedef struct ButtonExtra { BOOLEAN ReturnKey; BOOLEAN EscKey; BOOLEAN ExtraFat; } ButtonExtra; typedef struct BarExtra { struct ObjectNode *Parent; BOOLEAN FullSize; } BarExtra; typedef struct BoxExtra { STRPTR *Labels; STRPTR *Lines; AlignmentTypes AlignText; WORD MaxSize; BOOLEAN DrawBox; BOOLEAN ReserveSpace; } BoxExtra; typedef struct FrameExtra { UWORD InnerWidth; UWORD InnerHeight; BOOLEAN DrawBox; } FrameExtra; typedef struct PickerExtra { struct Gadget *Parent; struct Image *Image; } PickerExtra; typedef struct IncrementerExtra { struct Gadget *Parent; struct Image *Image; LONG Amount; } IncrementerExtra; typedef struct GroupExtra { struct MinList ObjectList; struct ObjectNode *ParentGroup; UWORD ExtraLeft; UWORD ExtraTop; LONG MaxOffset; LONG MaxSize; ULONG ActivePage; BOOLEAN Horizontal; BOOLEAN Paging; BOOLEAN Spread; BOOLEAN SameSize; BOOLEAN LastAttributes; } GroupExtra; typedef struct ListExtra { struct List *Labels; struct Gadget *Link; LONG LinkID; struct Hook *CallBack; ULONG ClickSeconds; ULONG ClickMicros; STRPTR *ExtraLabels; UWORD ExtraLabelWidth; UWORD MaxPen; UWORD MaxGrowX,MaxGrowY; BOOLEAN ReadOnly; BOOLEAN CursorKey; BOOLEAN AllocatedList; } ListExtra; typedef struct RadioExtra { STRPTR *Choices; UWORD LabelWidth; UBYTE TitlePlace; } RadioExtra; typedef struct TextExtra { STRPTR Text; struct Gadget *Picker; UWORD Len; BOOLEAN Border; BOOLEAN CopyText; BOOLEAN UsePicker; UBYTE Justification; } TextExtra; typedef struct NumberExtra { LONG Number; BOOLEAN Border; UBYTE Justification; } NumberExtra; typedef struct CycleExtra { STRPTR *Choices; } CycleExtra; typedef struct PalExtra { UBYTE *ColourTable; UWORD Depth; UWORD NumColours; BOOLEAN SmallPalette; } PalExtra; typedef struct SliderExtra { STRPTR LevelFormat; DISPFUNC DispFunc; LONG MaxLevelLen; LONG LevelWidth; STRPTR OriginalLabel; UBYTE LevelPlace; BOOLEAN FullLevelCheck; } SliderExtra; typedef struct StringExtra { struct LayoutHandle *LayoutHandle; struct Hook *HistoryHook; ULONG MaxHistoryLines; ULONG NumHistoryLines; struct Node *CurrentNode; STRPTR String; LONG MaxChars; struct Hook *EditHook; struct Gadget *Picker; STRPTR RealString; STRPTR Original; LONG LinkID; LONG Min; LONG Max; UBYTE Justification; BOOLEAN LastGadget; BOOLEAN UsePicker; } StringExtra; typedef struct IntegerExtra { struct LayoutHandle *LayoutHandle; struct Hook *HistoryHook; ULONG MaxHistoryLines; ULONG NumHistoryLines; struct Node *CurrentNode; LONG Number; LONG MaxChars; struct Hook *EditHook; LONG Min; LONG Max; UBYTE Justification; BOOLEAN LastGadget; BOOLEAN UseIncrementers; struct Gadget *LeftIncrementer; struct Gadget *RightIncrementer; struct Hook *IncrementerHook; } IntegerExtra; typedef struct ScrollerExtra { WORD Visible, ArrowSize; BOOLEAN RelVerify, Immediate, Arrows, Vertical, Thin; } ScrollerExtra; typedef struct ObjectNode { struct MinNode Node; struct Gadget *Host; struct ObjectNode *PointBack; STRPTR Label; LONG ID; UBYTE Type; PlacementTypes LabelPlace; BOOLEAN Disabled; PlacementTypes ObjectPlace; LONG Min; LONG Max; LONG Current; UWORD Left; UWORD Top; UWORD Width; UWORD Height; UWORD LabelWidth; UWORD Lines; UWORD Chars; WORD ExtraSpace; BOOLEAN NoKey; BOOLEAN HighLabel; BOOLEAN GroupIndent; BOOLEAN Centered; BOOLEAN PageSelector; UBYTE Key; APTR Storage; UBYTE StorageType; UBYTE Pad; union { GaugeExtra Gauge; TapeDeckExtra TapeDeck; ButtonExtra Button; BarExtra Bar; BoxExtra Box; FrameExtra Frame; PickerExtra Picker; IncrementerExtra Incrementer; GroupExtra Group; ListExtra List; RadioExtra Radio; TextExtra Text; NumberExtra Number; CycleExtra Cycle; PalExtra Palette; SliderExtra Slider; StringExtra String; IntegerExtra Integer; ScrollerExtra Scroller; } Special; } ObjectNode; typedef struct LayoutHandle { // WARNING: Beginning of this structure must match the definition in gui.h! struct Screen *Screen; struct DrawInfo *DrawInfo; struct Window *Window; APTR VisualInfo; struct Image *AmigaGlyph, *CheckGlyph; struct Screen *PubScreen; struct MsgPort *MsgPort; struct Gadget **GadgetArray; struct Gadget *Previous; struct Gadget *List; ULONG IDCMP; ObjectNode *ActiveIncrementer; LONG IncrementerCountdown; // Cached from DrawInfo structure UWORD TextPen; UWORD BackgroundPen; UWORD ShadowPen; UWORD ShinePen; UWORD AspectX; UWORD AspectY; struct Hook *LocaleHook; struct TextAttr *TextAttr; struct TextAttr *InitialTextAttr; struct TTextAttr CopyTextAttr; struct RastPort RPort; APTR Pool; UWORD GlyphWidth; UWORD InterWidth; UWORD InterHeight; LONG Count; LONG Index; LONG MaxID; ObjectNode *TopGroup; ObjectNode *CurrentGroup; ObjectNode *EscKey; ObjectNode *ReturnKey; ObjectNode *CursorKey; ObjectNode *GrowView; #ifdef DO_FRACTION_KIND struct Hook FracEditHook; #endif #ifdef DO_PASSWORD_KIND struct Hook PasswordEditHook; #endif #ifdef DO_HEXHOOK struct Hook HexEditHook; #endif struct Hook DefaultEditHook; struct Hook *StandardEditHook; struct Hook BackfillHook; #ifdef DO_PICKSHORTCUTS UBYTE Keys[256]; #endif struct Hook *HelpHook; // Hook to call when help key is pressed LONG MaxPen; BOOLEAN AutoRefresh; BOOLEAN CloseFont; BOOLEAN Failed; BOOLEAN Rescaled; BOOLEAN AutoActivate; BOOLEAN MoveToWindow; #ifdef DO_CLONING BOOLEAN CloningPermitted; // Genetic engineering? BOOLEAN ExactClone; // Make an exact copy, i.e. preserve all colours struct CloneExtra *CloneExtra; // Screen cloning information #endif struct timerequest TimeRequest; struct MsgPort TimePort; struct Window *Parent; // Parent of this window BOOL BlockParent; } LayoutHandle; typedef struct LockNode { struct MinNode MinNode; struct Window *Window; LONG Count; ULONG OldIDCMPFlags; struct Requester Requester; LONG MinWidth; LONG MinHeight; LONG MaxWidth; LONG MaxHeight; } LockNode; typedef struct ImageInfo { ULONG ImageType, GlyphWidth, GlyphHeight; } ImageInfo; #define IIA_ImageType (TAG_USER+739) #define IIA_GlyphWidth (TAG_USER+740) #define IIA_GlyphHeight (TAG_USER+741) typedef enum ImageTypes { IMAGECLASS_PICKER, IMAGECLASS_LEFTINCREMENTER, IMAGECLASS_RIGHTINCREMENTER, IMAGECLASS_BACKWARD, IMAGECLASS_FORWARD, IMAGECLASS_PREVIOUS, IMAGECLASS_NEXT, IMAGECLASS_RECORD, IMAGECLASS_PLAY, IMAGECLASS_STOP, IMAGECLASS_PAUSE, IMAGECLASS_REWIND, IMAGECLASS_EJECT } ImageTypes; typedef enum StorageTypes { STORAGE_BYTE,STORAGE_UBYTE, STORAGE_WORD,STORAGE_UWORD, STORAGE_LONG,STORAGE_ULONG, STORAGE_STRPTR } StorageTypes; /*****************************************************************************/ // A single colour in 96 bit precision struct ColourTriplet { ULONG Red, // 32 bits each Green, Blue; }; // A colour table ready to submit to LoadRGB32 struct ColourRecord { UWORD NumColours, // Number of colours in this chunk FirstColour; // First colour entry to set struct ColourTriplet Triplets[0]; // Table entries WORD Arnold; // Array terminator, needs to be set to zero }; // Screen reproduction struct CloneExtra { struct Screen *Screen; LONG *Pens; UWORD *ScreenPens; UWORD MinWidth, MinHeight, MaxWidth, MaxHeight, TotalPens; UBYTE Depth; struct IBox Bounds; }; /*****************************************************************************/ STATIC VOID __regargs LTK_LayoutGroup(LayoutHandle *Handle, ObjectNode *Group); /*****************************************************************************/ STATIC ULONG ghostingPat = 0x44441111; STATIC struct ExecBase *SysBase; STATIC struct Library *IntuitionBase; STATIC struct GfxBase *GfxBase; STATIC struct Library *UtilityBase; STATIC struct Library *GadToolsBase; STATIC struct Library *KeymapBase; STATIC struct Library *LocaleBase; STATIC struct Locale *LTK_Locale; STATIC struct SignalSemaphore LTK_LockSemaphore; STATIC struct MinList LTK_LockList; STATIC struct IClass *LTK_ImageClass; STATIC BOOLEAN V39, V40; #ifdef DO_PICKSHORTCUTS STATIC UBYTE LTK_Keys[2][256]; STATIC struct SignalSemaphore LTK_KeySemaphore; STATIC BOOLEAN LTK_KeysInitialized; #endif /*****************************************************************************/ STATIC ULONG __regargs Atol(STRPTR String) { ULONG Value = 0; while(*String == ' ' || *String == '\t') String++; while(*String) { if(*String >= '0' && *String <= '9') Value = (Value * 10) + (*String++) - '0'; else break; } return(Value); } /*****************************************************************************/ STATIC ULONG __asm __saveds LTK_BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort) { struct LayoutHandle *Handle = (struct LayoutHandle *)Hook -> h_Data; struct RastPort RastPort = *RPort; RPort = &RastPort; RPort -> Layer = NULL; SetAPen(RPort,Handle -> BackgroundPen); SetDrMd(RPort,JAM1); RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY); return(TRUE); } /*****************************************************************************/ #ifdef DO_HEXHOOK // Check whether the buffer only contains a valid hex/binary/octal number... STATIC BOOLEAN __regargs LTK_ConvertNum(BOOLEAN negAllowed,STRPTR buffer,LONG *value) { UBYTE ch; ULONG num; UWORD i; LONG neg; num = 0; if((buffer[0] == '-') && negAllowed) { neg = -1; buffer++; } else neg = 1; if(((buffer[0] == '0') && (buffer[1] == 'x')) || (buffer[0] == '$')) { if (buffer[0] == '$') i = 1; else i = 2; while(buffer[i]) { ch = ToUpper(buffer[i]); num = num * 16; if((ch >= 'A') && (ch <= 'F')) num += ch - 'A' + 10; else { if ((ch >= '0') && (ch <= '9')) num += ch - '0'; else return(FALSE); } i++; } *value = num * neg; return(TRUE); } else { if(buffer[0] == '%') { i = 1; while(buffer[i]) { ch = buffer[i]; if((ch < '0') || (ch > '1')) return(FALSE); num = (num * 2) + ch - '0'; i++; } } else { if(buffer[0] == '&') { i = 1; while(buffer[i]) { ch = buffer[i]; if((ch < '0') || (ch > '7')) return(FALSE); num = (num * 8) + ch - '0'; i++; } } else { i = 0; while(buffer[i]) { ch = buffer[i]; if((ch < '0') || (ch > '9')) return(FALSE); num = (num * 10) + ch - '0'; i++; } } } *value = num * neg; return(TRUE); } return(FALSE); } #endif /*****************************************************************************/ STATIC VOID __regargs LTK_AddHistory(struct SGWork *Work) { ObjectNode *Node; if(GETOBJECT(Work -> Gadget,Node)) { if(Node -> Special . String . HistoryHook) { struct MinList *List = Node -> Special . String . HistoryHook -> h_Data; while(Node -> Special . String . NumHistoryLines >= Node -> Special . String . MaxHistoryLines) { CallHookPkt(Node -> Special . String . HistoryHook,Work -> Gadget,NULL); Node -> Special . String . NumHistoryLines--; } Work -> WorkBuffer[Work -> NumChars] = 0; if(CallHookPkt(Node -> Special . String . HistoryHook,Work -> Gadget,Work -> WorkBuffer)) Node -> Special . String . NumHistoryLines++; if(List -> mlh_Head -> mln_Succ) Node -> Special . String . CurrentNode = (struct Node *)List -> mlh_TailPred; else Node -> Special . String . CurrentNode = NULL; } } } STATIC VOID __regargs LTK_HandleHistory(struct SGWork *Work) { ObjectNode *Node; if(GETOBJECT(Work -> Gadget,Node)) { if(Node -> Special . String . HistoryHook) { struct Node *Choice = NULL; struct MinList *List = Node -> Special . String . HistoryHook -> h_Data; if(Work -> IEvent -> ie_Qualifier & QUALIFIER_SHIFT) { if(Work -> IEvent -> ie_Code == CURSORUP) { if(List -> mlh_Head -> mln_Succ) Choice = (struct Node *)List -> mlh_Head; } else { if(List -> mlh_Head -> mln_Succ) Choice = (struct Node *)List -> mlh_TailPred; } } else { struct Node *Current = Node -> Special . String . CurrentNode; if(Work -> IEvent -> ie_Code == CURSORUP) { if(Current) { if(Current -> ln_Pred -> ln_Pred) Choice = Current -> ln_Pred; else Choice = Current; } else { if(List -> mlh_Head -> mln_Succ) Choice = (struct Node *)List -> mlh_TailPred; } } else { if(Current) { if(Current -> ln_Succ -> ln_Succ) Choice = Current -> ln_Succ; } } } if(Choice != Node -> Special . String . CurrentNode) { if(Choice) { strcpy(Work -> WorkBuffer,Choice -> ln_Name); Work -> NumChars = Work -> BufferPos = strlen(Work -> WorkBuffer); } else { Work -> WorkBuffer[0] = 0; Work -> NumChars = 0; Work -> BufferPos = 0; } if(Node -> Type == INTEGER_KIND) { #ifdef DO_HEXHOOK LTK_ConvertNum((Node -> Special . Integer . Min < 0),Work -> WorkBuffer,&Work -> LongInt); #else Work -> LongInt = Atol(Work -> WorkBuffer); #endif } Node -> Special . String . CurrentNode = Choice; Work -> Actions = (Work -> Actions & ~SGA_BEEP) | SGA_USE | SGA_REDISPLAY; } } } } /*****************************************************************************/ #ifdef DO_FRACTION_KIND STATIC ULONG __asm __saveds LTK_FracEditRoutine(register __a0 struct Hook *Hook,register __a2 struct SGWork *Work,register __a1 ULONG *Msg) { if(*Msg == SGH_KEY) { if(Work -> IEvent -> ie_Code == CURSORUP || Work -> IEvent -> ie_Code == CURSORDOWN) LTK_HandleHistory(Work); if(Work -> EditOp == EO_ENTER) { LayoutHandle *Handle = Hook -> h_Data; ObjectNode *Node; BOOLEAN Activate = TRUE; if(GETOBJECT(Work -> Gadget,Node)) { if(Node -> Type == FRACTION_KIND && Node -> Special . String . LastGadget) Activate = FALSE; } if(!(Work -> IEvent -> ie_Qualifier & QUALIFIER_SHIFT)) { if(Activate && Handle -> AutoActivate) Work -> Actions |= SGA_NEXTACTIVE; if(!(Work -> Actions & SGA_NEXTACTIVE)) Work -> Code = '\r'; } } if(Work -> EditOp == EO_INSERTCHAR || Work -> EditOp == EO_REPLACECHAR) { UBYTE DecimalPoint = (LTK_Locale ? LTK_Locale -> loc_DecimalPoint[0] : '.'); if(Work -> Code == DecimalPoint || (Work -> Code >= '0' && Work -> Code <= '9')) { if(Work -> Code == DecimalPoint) { BOOLEAN UseIt = TRUE; LONG i; for (i = 0 ; UseIt && i < Work -> NumChars ; i++) { if(Work -> PrevBuffer[i] == DecimalPoint) UseIt = FALSE; } if(!UseIt) { Work -> Actions &= ~SGA_USE; Work -> Actions |= SGA_BEEP; } } } else { Work -> Actions &= ~SGA_USE; Work -> Actions |= SGA_BEEP; } } if(Work -> Actions & SGA_END) LTK_AddHistory(Work); } else { if(*Msg != SGH_CLICK) return(FALSE); } return(TRUE); } #endif /*****************************************************************************/ STATIC ULONG __asm __saveds LTK_DefaultEditRoutine(register __a0 struct Hook *Hook,register __a2 struct SGWork *Work,register __a1 ULONG *Msg) { if(*Msg == SGH_KEY) { if(Work -> IEvent -> ie_Code == CURSORUP || Work -> IEvent -> ie_Code == CURSORDOWN) LTK_HandleHistory(Work); if(Work -> EditOp == EO_ENTER) { LayoutHandle *Handle = Hook -> h_Data; ObjectNode *Node; BOOLEAN Activate = TRUE; if(GETOBJECT(Work -> Gadget,Node)) { if(Node -> Type == STRING_KIND) { if(Node -> Special . String . LastGadget) Activate = FALSE; } #ifndef DO_HEXHOOK else { if(Node -> Type == INTEGER_KIND) { if(Node -> Special . Integer . LastGadget) Activate = FALSE; } } #endif } if(!(Work -> IEvent -> ie_Qualifier & QUALIFIER_SHIFT)) { if(Activate && Handle -> AutoActivate) Work -> Actions |= SGA_NEXTACTIVE; if(!(Work -> Actions & SGA_NEXTACTIVE)) Work -> Code = '\r'; } } if(Work -> IEvent -> ie_Code == CURSORRIGHT && (Work -> IEvent -> ie_Qualifier & QUALIFIER_CONTROL)) { if(Work -> BufferPos != Work -> NumChars) { WORD i,Position = -1; for(i = Work -> BufferPos ; i < Work -> NumChars ; i++) { if(Work -> WorkBuffer[i] == ' ') { for( ; i < Work -> NumChars ; i++) { if(Work -> WorkBuffer[i] != ' ') { Position = i; break; } } break; } } if(Position != -1) Work -> BufferPos = Position; else Work -> BufferPos = Work -> NumChars; Work -> EditOp = EO_MOVECURSOR; } } if(Work -> IEvent -> ie_Code == CURSORLEFT && (Work -> IEvent -> ie_Qualifier & QUALIFIER_CONTROL)) { if(Work -> BufferPos) { WORD i,Position = -1; for(i = Work -> BufferPos ; i >= 0 ; i--) { if(Work -> WorkBuffer[i] != ' ') { Position = i; break; } } if(Position == -1) Position = 0; if(Position) { i = Position; Position = -1; for( ; i >= 0 ; i--) { if(Work -> WorkBuffer[i] == ' ') { Position = i + 1; break; } } } if(Position != -1) Work -> BufferPos = Position; else Work -> BufferPos = 0; Work -> EditOp = EO_MOVECURSOR; } } if(Work -> Actions & SGA_END) LTK_AddHistory(Work); } else { if(*Msg != SGH_CLICK) return(FALSE); } return(TRUE); } /*****************************************************************************/ #ifdef DO_HEXHOOK STATIC ULONG __asm __saveds LTK_HexEditRoutine(register __a0 struct Hook *hook,register __a2 struct SGWork *sgw,register __a1 ULONG *msg) { ULONG result = FALSE; if(*msg == SGH_KEY) { BOOLEAN activate = TRUE; LayoutHandle *handle = hook -> h_Data; ObjectNode *node; if(sgw -> IEvent -> ie_Code == CURSORUP || sgw -> IEvent -> ie_Code == CURSORDOWN) LTK_HandleHistory(sgw); if(GETOBJECT(sgw -> Gadget,node)) { if(node -> Type == INTEGER_KIND) { if(node -> Special . Integer . LastGadget) activate = FALSE; result = TRUE; if(!LTK_ConvertNum((node -> Special . Integer . Min < 0),sgw -> WorkBuffer,(LONG *)&sgw -> StringInfo -> LongInt)) { sgw -> EditOp = EO_BADFORMAT; sgw -> Actions = SGA_BEEP; } } } if(sgw -> EditOp == EO_ENTER && !(sgw -> IEvent -> ie_Qualifier & QUALIFIER_SHIFT)) { if(activate && handle -> AutoActivate) sgw -> Actions |= SGA_NEXTACTIVE; if(!(sgw -> Actions & SGA_NEXTACTIVE)) sgw -> Code = '\r'; } if(sgw -> Actions & SGA_END) LTK_AddHistory(sgw); } return(result); } #endif /*****************************************************************************/ #ifdef DO_PASSWORD_KIND STATIC ULONG __asm __saveds LTK_PasswordEditRoutine(register __a0 struct Hook *Hook,register __a2 struct SGWork *Work,register __a1 ULONG *Msg) { ObjectNode *Node; if(GETOBJECT(Work -> Gadget,Node)) { STRPTR Buffer = Node -> Special . String . RealString; STRPTR Original = Node -> Special . String . Original; WORD Len; /* if(Work -> IEvent -> ie_Code == CURSORUP || Work -> IEvent -> ie_Code == CURSORDOWN)*/ /* LTK_HandleHistory(Work);*/ switch(*Msg) { case SGH_KEY: switch(Work -> EditOp) { case EO_INSERTCHAR: Buffer[Work -> BufferPos - 1] = Work -> Code; Buffer[Work -> NumChars] = 0; Work -> Code = (WORD)'·'; Work -> WorkBuffer[Work -> BufferPos - 1] = (UBYTE)'·'; break; case EO_RESET: Len = strlen(Original); strcpy(Buffer,Original); memset(Work -> WorkBuffer,'·',Len); Work -> WorkBuffer[Len] = 0; Work -> NumChars = Len; Work -> BufferPos = Len; Work -> EditOp = EO_BIGCHANGE; break; case EO_CLEAR: Work -> WorkBuffer[0] = 0; Work -> NumChars = 0; Work -> BufferPos = 0; Work -> EditOp = EO_BIGCHANGE; Buffer[0] = 0; break; case EO_DELBACKWARD: Buffer[Work -> NumChars] = 0; break; case EO_NOOP: break; case EO_ENTER: strcpy(Original,Buffer); if(!(Work -> IEvent -> ie_Qualifier & QUALIFIER_SHIFT)) { if(!Node -> Special . String . LastGadget && Node -> Special . String . LayoutHandle -> AutoActivate) Work -> Actions |= SGA_NEXTACTIVE; if(!(Work -> Actions & SGA_NEXTACTIVE)) Work -> Code = '\r'; } break; case EO_MOVECURSOR: case EO_DELFORWARD: Work -> Actions &= ~SGA_USE; break; default: Work -> Actions &= ~SGA_USE; Work -> Actions |= SGA_BEEP; break; } break; case SGH_CLICK: Work -> BufferPos = Work -> NumChars; Work -> EditOp = EO_BIGCHANGE; break; } /* if(Work -> Actions & SGA_END)*/ /* LTK_AddHistory(Work);*/ return(TRUE); } else return(FALSE); } #endif /*****************************************************************************/ STATIC VOID __regargs LTK_SetPens(struct RastPort *rp, UWORD apen, UWORD bpen,UBYTE mode) { if(V39) SetABPenDrMd(rp,apen,bpen,mode); else { if(apen != rp -> FgPen) SetAPen(rp,apen); if(bpen != rp -> BgPen) SetBPen(rp,bpen); if(mode != rp -> DrawMode) SetDrMd(rp,mode); } } /*****************************************************************************/ STATIC VOID __regargs LTK_SetAPen(struct RastPort *rp,UWORD apen) { if(V39) { if(GetAPen(rp) != apen) SetAPen(rp,apen); } else { if(apen != rp -> FgPen) SetAPen(rp,apen); } } /*****************************************************************************/ STATIC VOID __regargs LTK_SetFont(LayoutHandle *handle,struct TextFont *font) { SetFont(&handle -> RPort,font); if(handle -> Window) SetFont(handle -> Window -> RPort,font); } /*****************************************************************************/ STATIC VOID __regargs LTK_DrawBevelBox(LayoutHandle *handle,ObjectNode *node) { DrawBevelBox(&handle -> RPort,node -> Left,node -> Top,node -> Width,node -> Height, GT_VisualInfo, handle -> VisualInfo, GTBB_Recessed, TRUE, TAG_DONE); } /*****************************************************************************/ STATIC VOID __regargs LTK_PlaceText(LayoutHandle *handle,STRPTR text,ULONG textLen,LONG x,LONG y) { Move(&handle -> RPort,x,y); Text(&handle -> RPort,text,textLen); } /*****************************************************************************/ STATIC VOID __regargs LTK_GetDisplayClip(struct Screen *screen,WORD *left,WORD *top,WORD *width,WORD *height) { struct TagItem tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE }; if(!VideoControl(screen -> ViewPort . ColorMap,tags)) { struct ViewPortExtra *vpe = (struct ViewPortExtra *)tags[0] . ti_Data; struct Rectangle clip; QueryOverscan(GetVPModeID(&screen -> ViewPort),&clip,OSCAN_TEXT); *width = vpe -> DisplayClip . MaxX - vpe -> DisplayClip . MinX + 1; *height = vpe -> DisplayClip . MaxY - vpe -> DisplayClip . MinY + 1; if(*width < clip . MaxX - clip . MinX + 1) *width = clip . MaxX - clip . MinX + 1; if(*height < clip . MaxY - clip . MinY + 1) *height = clip . MaxY - clip . MinY + 1; if(*width > screen -> Width) *width = screen -> Width; if(*height > screen -> Height) *height = screen -> Height; } else { *width = screen -> Width; *height = screen -> Height; } *left = screen -> LeftEdge; *top = screen -> TopEdge; if(*left > 0) *left = 0; else *left = -(*left); if(*top > 0) *top = 0; else *top = -(*top); if((*left > screen -> Width) || (*left < 0)) *left = 0; if ((*top > screen -> Height) || (*top < 0)) *top = 0; } /*****************************************************************************/ STATIC VOID __regargs LTK_MoveToWindow(LayoutHandle *handle) { if(V39 && handle -> MoveToWindow) { WORD left,top,width,height; LTK_GetDisplayClip(handle->Screen,&left,&top,&width,&height); if(handle -> Window -> Width < width) left = (width - handle -> Window -> Width) / 2; else left = 0; if(handle -> Window -> Height < height) top = (height - handle -> Window -> Height) / 2; else top = 0; if((left = handle -> Window -> LeftEdge - left) < 0) left = 0; if((top = handle -> Window -> TopEdge - top) < 0) top = 0; ScreenPosition(handle -> Screen,SPOS_MAKEVISIBLE,left,top,left + width - 1,top + height - 1); } } /*****************************************************************************/ STATIC VOID __regargs LTK_GetStorage(ObjectNode *Node) { if(Node -> Storage) { LONG Number = 0; STRPTR String = NULL; switch(Node -> StorageType) { case STORAGE_BYTE: Number = *(BYTE *)Node -> Storage; break; case STORAGE_UBYTE: Number = *(UBYTE *)Node -> Storage; break; case STORAGE_WORD: Number = *(WORD *)Node -> Storage; break; case STORAGE_UWORD: Number = *(UWORD *)Node -> Storage; break; case STORAGE_LONG: Number = *(LONG *)Node -> Storage; break; case STORAGE_ULONG: Number = *(ULONG *)Node -> Storage; break; case STORAGE_STRPTR: String = Node -> Storage; break; } switch(Node -> Type) { case CHECKBOX_KIND: case LISTVIEW_KIND: case MX_KIND: case CYCLE_KIND: case PALETTE_KIND: case SLIDER_KIND: case SCROLLER_KIND: #ifdef DO_GAUGE_KIND case GAUGE_KIND: #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: #endif /* DO_TAPEDECK_KIND */ #ifdef DO_FRACTION_KIND case FRACTION_KIND: #endif Node -> Current = Number; break; case STRING_KIND: #ifdef DO_PASSWORD_KIND case PASSWORD_KIND: #endif Node -> Special . String . String = String; break; case INTEGER_KIND: Node -> Special . Integer . Number = Number; break; } } } STATIC VOID __regargs LTK_PutStorage(ObjectNode *Node) { if(Node -> Storage) { LONG Number = 0; STRPTR String = NULL; switch(Node -> Type) { case CHECKBOX_KIND: case LISTVIEW_KIND: case MX_KIND: case CYCLE_KIND: case PALETTE_KIND: case SLIDER_KIND: case SCROLLER_KIND: #ifdef DO_GAUGE_KIND case GAUGE_KIND: #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: #endif /* DO_TAPEDECK_KIND */ Number = Node -> Current; break; #ifdef DO_FRACTION_KIND case FRACTION_KIND: Number = (LONG)LT_String2Fixed(((struct StringInfo *)Node -> Host -> SpecialInfo) -> Buffer); break; #endif #ifdef DO_PASSWORD_KIND case PASSWORD_KIND: String = Node -> Special . String . Original; break; #endif case STRING_KIND: String = ((struct StringInfo *)Node -> Host -> SpecialInfo) -> Buffer; break; case INTEGER_KIND: Number = ((struct StringInfo *)Node -> Host -> SpecialInfo) -> LongInt; break; } switch(Node -> StorageType) { case STORAGE_BYTE: if(!String) *(BYTE *)Node -> Storage = (BYTE)Number; break; case STORAGE_UBYTE: if(!String) *(UBYTE *)Node -> Storage = (UBYTE)Number; break; case STORAGE_WORD: if(!String) *(WORD *)Node -> Storage = (WORD)Number; break; case STORAGE_UWORD: if(!String) *(UWORD *)Node -> Storage = (UWORD)Number; break; case STORAGE_LONG: if(!String) *(LONG *)Node -> Storage = (LONG)Number; break; case STORAGE_ULONG: if(!String) *(ULONG *)Node -> Storage = (ULONG)Number; break; case STORAGE_STRPTR: if(String) strcpy(Node -> Storage,String); break; } } } /*****************************************************************************/ STATIC VOID __stdargs sprintf(STRPTR buffer, STRPTR formatString,...) { va_list varArgs; va_start(varArgs,formatString); RawDoFmt(formatString,varArgs,(VOID (*)())(VOID (*))"\x16\xC0\x4E\x75",buffer); va_end(varArgs); } /*****************************************************************************/ STATIC VOID __regargs LTK_BlinkButton(LayoutHandle *handle,struct Gadget *gadget) { if((gadget -> Flags & (GFLG_GADGIMAGE | GFLG_GADGHIMAGE)) && gadget -> SelectRender) DrawImageState(&handle -> RPort,gadget -> SelectRender,gadget -> LeftEdge,gadget -> TopEdge,IDS_SELECTED,handle -> DrawInfo); if(handle -> TimeRequest . tr_node . io_Device) { Forbid(); handle -> TimePort . mp_SigTask = SysBase -> ThisTask; handle -> TimeRequest . tr_node . io_Command = TR_ADDREQUEST; handle -> TimeRequest . tr_time . tv_secs = 0; handle -> TimeRequest . tr_time . tv_micro = 80000; SetSignal(0,SIGF_SINGLE); DoIO(&handle -> TimeRequest); Permit(); } else TimeDelay(UNIT_VBLANK,0,80000); if ((gadget -> Flags & GFLG_GADGIMAGE) && gadget -> GadgetRender) DrawImageState(&handle -> RPort,gadget -> GadgetRender,gadget -> LeftEdge,gadget -> TopEdge,IDS_NORMAL,handle -> DrawInfo); } /*****************************************************************************/ #ifdef DO_GAUGE_KIND STATIC VOID __regargs LTK_DrawGauge(LayoutHandle *handle,ObjectNode *node,LONG percent,BOOLEAN fullRefresh) { struct RastPort *rp = &handle -> RPort; if(fullRefresh) { LONG top = node -> Top + node -> Height - (handle -> RPort . TxHeight + 2); LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,node -> Left,node -> Top,node -> Left + node -> Width - 1,node -> Top + node -> Height - 1); DrawBevelBox(rp,node -> Left,node -> Top,node -> Width,node -> Height - (handle -> InterHeight + handle -> RPort . TxHeight + 2), GT_VisualInfo, handle -> VisualInfo, GTBB_Recessed, TRUE, TAG_DONE); LTK_SetPens(rp,handle -> TextPen,0,JAM1); LTK_PlaceText(handle,"0%",2,node -> Left,top + handle -> RPort . TxBaseline); LTK_PlaceText(handle,"100%",4,node -> Left + node -> Width - TextLength(rp,"100%",4),top + handle -> RPort . TxBaseline); if(node -> Width >= TextLength(rp,"0% 50% 100%",11)) { LONG i,left,total = node -> Width - 2; LTK_PlaceText(handle,"50%",3,node -> Left + (node -> Width - TextLength(rp,"50%",3)) / 2,top + handle -> RPort . TxBaseline); top -= handle -> InterHeight; for (i = 0 ; i < 5 ; i++) { left = (total * i) / 4; RectFill(rp,node -> Left + left,top,node -> Left + left + 1,top + 1); } } else { LONG i,left,total = node -> Width - 2; top -= handle -> InterHeight; for (i = 0; i < 3; i++) { left = (total * i) / 2; RectFill(rp,node -> Left + left,top,node -> Left + left + 1,top + 1); } } } if(node -> Special . Gauge . InfoLength && node -> Special . Gauge . InfoText[0]) { LONG height = node -> Height - (1 + handle -> InterHeight + handle -> RPort . TxHeight + 2 + 1); LONG width = node -> Width - (2 + 2); LONG left = 0; LONG right = (width * percent) / 100; struct TextExtent Extent; LONG len; if(right) { LTK_SetAPen(rp,handle -> DrawInfo -> dri_Pens[FILLPEN]); RectFill(rp,node -> Left + 2 + left,node -> Top + 1,node -> Left + 2 + right - 1,node -> Top + 1 + height - 1); } if(right < width) { left = right; right = width; LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,node -> Left + 2 + left,node -> Top + 1,node -> Left + 2 + right - 1,node -> Top + 1 + height - 1); } if(handle -> DrawInfo -> dri_Pens[FILLTEXTPEN] == handle -> DrawInfo -> dri_Pens[BACKGROUNDPEN]) { if(handle -> DrawInfo -> dri_Pens[TEXTPEN] == handle -> DrawInfo -> dri_Pens[FILLPEN]) LTK_SetPens(rp,handle -> DrawInfo -> dri_Pens[TEXTPEN],handle -> BackgroundPen,JAM1 | COMPLEMENT); else LTK_SetPens(rp,handle -> DrawInfo -> dri_Pens[TEXTPEN],handle -> BackgroundPen,JAM1); } else { if(handle -> DrawInfo -> dri_Pens[FILLTEXTPEN] == handle -> DrawInfo -> dri_Pens[FILLPEN]) LTK_SetPens(rp,handle -> DrawInfo -> dri_Pens[FILLTEXTPEN],handle -> BackgroundPen,JAM1 | COMPLEMENT); else LTK_SetPens(rp,handle -> DrawInfo -> dri_Pens[FILLTEXTPEN],handle -> BackgroundPen,JAM1); } len = TextFit(rp,node -> Special . Gauge . InfoText,strlen(node -> Special . Gauge . InfoText),&Extent,NULL,1,width,32767); LTK_PlaceText(handle,node -> Special . Gauge . InfoText,len,node -> Left + 2 + (width - Extent . te_Width) / 2,node -> Top + 1 + (height - rp -> Font -> tf_YSize) / 2 + rp -> Font -> tf_Baseline); LTK_SetPens(rp,handle -> TextPen,handle->BackgroundPen,JAM1); } else { if(node -> Current < percent) { LONG height = node -> Height - (1 + handle -> InterHeight + handle -> RPort . TxHeight + 2 + 1); LONG width = node -> Width - (2 + 2); LONG left = (width * node -> Current) / 100; LONG right = (width * percent) / 100; if(right) { LTK_SetAPen(rp,handle -> DrawInfo -> dri_Pens[FILLPEN]); RectFill(rp,node -> Left + 2 + left,node -> Top + 1,node -> Left + 2 + right - 1,node -> Top + 1 + height - 1); } } else { if(node -> Current > percent) { LONG height = node -> Height - (1 + handle -> InterHeight + handle -> RPort . TxHeight + 2 + 1); LONG width = node -> Width - (2 + 2); LONG left = (width * percent) / 100; LONG right = (width * node -> Current) / 100; if(right) { LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,node -> Left + 2 + left,node -> Top + 1,node -> Left + 2 + right - 1,node -> Top + 1 + height - 1); } } } } node -> Current = percent; LTK_PutStorage(node); } #endif /*****************************************************************************/ STATIC VOID __regargs LTK_PrintLine(LayoutHandle *handle,UBYTE alignType,LONG left,LONG top,LONG space,STRPTR line,LONG len) { struct RastPort *rp; LONG width; struct TextExtent extent; rp = &handle -> RPort; len = TextFit(rp,line,len,&extent,NULL,1,space,32767); width = extent . te_Width; if(len) { LTK_SetPens(rp,handle -> TextPen,handle -> BackgroundPen,JAM2); if(alignType == ALIGNTEXT_CENTERED) { LTK_PlaceText(handle,line,len,left + (space - width) / 2,top + handle -> RPort . TxBaseline); if(width < space) { LONG fill; LTK_SetAPen(rp,handle -> BackgroundPen); if((fill = (space - width) / 2) > 0) RectFill(rp,left,top,left + fill - 1,top + handle -> RPort . TxHeight - 1); if((fill = space - ((space - width) / 2)) > 0) RectFill(rp,left + fill,top,left + space - 1,top + handle -> RPort . TxHeight - 1); } } else { if(alignType == ALIGNTEXT_LEFT) { LTK_PlaceText(handle,line,len,left,top + handle -> RPort.TxBaseline); if(left + width <= left + space - 1) { LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,left + width,top,left + space - 1,top + handle -> RPort . TxHeight - 1); } } else { LTK_PlaceText(handle,line,len,left + space - width,top + handle -> RPort . TxBaseline); if(width < space) { LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,left,top,left + space - width - 1,top + handle -> RPort . TxHeight - 1); } } } } else { LTK_SetAPen(rp,handle -> BackgroundPen); RectFill(rp,left,top,left + space - 1,top + handle -> RPort . TxHeight - 1); } } /*****************************************************************************/ STATIC VOID __regargs LTK_PrintLinePadded(LayoutHandle *Handle,LONG Left,LONG Top,LONG Space,STRPTR Line,LONG Len) { struct RastPort *RPort = &Handle -> RPort; LONG Size = 0; LONG Start = 0; LONG Count = 0; LONG i = 0; LONG Width = 0; while(i < Len && Line[i] == ' ') { Size++; i++; } while(i < Len) { while(i < Len && Line[i] != ' ') { Size++; i++; } Width += TextLength(RPort,&Line[Start],Size); Count++; while(i < Len && Line[i] == ' ') i++; Start = i; Size = 0; } if(Width) { LONG j; Space -= Width; j = Start = Size = 0; while(j < Len && Line[j] == ' ') { Size++; j++; } LTK_SetPens(RPort,Handle -> TextPen,Handle -> BackgroundPen,JAM2); Move(RPort,Left,Top + RPort -> TxBaseline); Count--; for(i = 0 ; i <= Count ; i++) { if(i) { LONG Delta; if(Delta = (Space * i) / Count - (Space * (i - 1)) / Count) { LTK_SetAPen(RPort,Handle -> BackgroundPen); RectFill(RPort,RPort -> cp_x,Top,RPort -> cp_x + Delta - 1,Top + RPort -> TxHeight - 1); LTK_SetAPen(RPort,Handle -> TextPen); Move(RPort,RPort -> cp_x + Delta,RPort -> cp_y); } } while(j < Len && Line[j] != ' ') { Size++; j++; } Text(RPort,&Line[Start],Size); while(j < Len && Line[j] == ' ') j++; Start = j; Size = 0; } } else { LTK_SetAPen(RPort,Handle -> BackgroundPen); RectFill(RPort,Left,Top,Left + Space - 1,Top + RPort -> TxHeight - 1); } } /*****************************************************************************/ STATIC VOID __regargs LTK_PrintBoxLine(LayoutHandle *handle,ObjectNode *node,LONG index) { if(node -> Special . Box . Lines && node -> Special . Box . Lines[index]) { LONG len = strlen(node -> Special . Box . Lines[index]); if(node -> Special . Box . AlignText == ALIGNTEXT_PAD) LTK_PrintLinePadded(handle,node -> Left + 4,node -> Top + 2 + index * handle -> RPort . TxHeight,node -> Width - 8,node -> Special . Box . Lines[index],len); else LTK_PrintLine(handle,node -> Special . Box . AlignText,node -> Left + 4,node -> Top + 2 + index * handle -> RPort . TxHeight,node -> Width - 8,node -> Special . Box . Lines[index],len); } } /*****************************************************************************/ STATIC VOID __regargs LTK_ResetGroups(ObjectNode *group) { ObjectNode *node; group -> Special . Group . ExtraLeft = 0; group -> Special . Group . ExtraTop = 0; group -> Special . Group . MaxOffset = 0; group -> Special . Group . MaxSize = 0; group -> GroupIndent = FALSE; group -> Left = 0; group -> Top = 0; group -> Width = 0; group -> Height = 0; SCANGROUP(group,node) { if(node -> Type == GROUP_KIND) LTK_ResetGroups(node); } } /*****************************************************************************/ STATIC BOOLEAN __regargs LTK_Rescale(LayoutHandle *handle,BOOLEAN trimWidth,BOOLEAN trimHeight) { STATIC struct TextAttr topazAttr = { "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED }; LONG oldWidth; LONG oldHeight; UBYTE glyph; LONG glyphWidth; LONG count; LONG i; LONG total; BOOLEAN found; oldWidth = handle -> GlyphWidth; oldHeight = handle -> RPort . TxHeight; if(handle -> CloseFont) { CloseFont(handle -> RPort . Font); handle -> CloseFont = FALSE; } /* GfxBase -> DefaultFont is guaranteed not to ever be removed from * memory,so we use that fact... */ LTK_SetFont(handle,GfxBase -> DefaultFont); handle -> TextAttr = &handle -> CopyTextAttr; handle -> CopyTextAttr . tta_Name = handle -> RPort . Font -> tf_Message . mn_Node . ln_Name; handle -> CopyTextAttr . tta_YSize = handle -> RPort . TxHeight; handle -> CopyTextAttr . tta_Style = handle -> RPort . Font -> tf_Style; handle -> CopyTextAttr . tta_Flags = handle -> RPort . TxFlags; if(handle -> RPort . Font -> tf_Style & FSF_TAGGED) handle -> CopyTextAttr . tta_Tags = ((struct TextFontExtension *)handle -> RPort . Font -> tf_Extension) -> tfe_Tags; FOREVER { count = 0; total = 0; for(i = 32 ; i < 127 ; i++) { glyph = i; total += TextLength(&handle -> RPort,&glyph,1); count++; } for(i = 160 ; i < 256 ; i++) { glyph = i; total += TextLength(&handle -> RPort,&glyph,1); count++; } glyphWidth = total / count; found = TRUE; if(trimWidth && (glyphWidth >= oldWidth)) found = FALSE; if(trimHeight && (oldHeight >= handle -> RPort . TxHeight)) found = FALSE; if(found) { handle -> GlyphWidth = glyphWidth; handle -> Rescaled = TRUE; if(glyphWidth <= 8) handle -> InterWidth = 4; else handle -> InterWidth = glyphWidth / 2; if(handle -> RPort . TxHeight <= 8) handle -> InterHeight = 2; else handle -> InterHeight = handle -> RPort . TxHeight / 4; LTK_ResetGroups(handle -> TopGroup); return(TRUE); } if(handle -> TextAttr == &topazAttr) return(FALSE); LTK_SetFont(handle,OpenFont(&topazAttr)); handle -> TextAttr = &topazAttr; handle -> CloseFont = TRUE; } } /*****************************************************************************/ STATIC VOID __regargs LTK_DrawIncrementer(struct RastPort *rp,BOOLEAN leftDirection,LONG left,LONG top,LONG width,LONG height) { LONG middle; LONG x0,x1; LONG stop; middle = height / 2; if(leftDirection) { x0 = left + 2; x1 = left + width - 3; } else { x0 = left + width - 3; x1 = left + 2; } if(height > width) stop = (width - 4) / 2; else stop = (height - 4) / 2; Move(rp,x0,top + middle); Draw(rp,x1,top + middle - stop); Move(rp,x0,top + middle); Draw(rp,x1,top + middle + stop); } /*****************************************************************************/ #ifdef DO_TAPEDECK_KIND STATIC VOID __regargs LTK_DrawBackFore(struct RastPort *RPort,BOOLEAN Back,LONG Left,LONG Top,LONG Width,LONG Height) { LONG i,Len,Start,ArrowWidth,ArrowHeight,Shift; ArrowWidth = Width / 2; ArrowHeight = Height; Left = Left + (Width - ArrowWidth) / 2; Shift = ArrowWidth / 2; if(Back) { for(i = 0 ; i < ArrowWidth ; i++) { Len = (ArrowHeight * (i + 1)) / ArrowWidth; Start = Top + (ArrowHeight - Len) / 2; Move(RPort,Left + i - Shift,Start); Draw(RPort,Left + i - Shift,Start + Len - 1); Move(RPort,Left + i + Shift,Start); Draw(RPort,Left + i + Shift,Start + Len - 1); } } else { for(i = 0 ; i < ArrowWidth ; i++) { Len = (ArrowHeight * (i + 1)) / ArrowWidth; Start = Top + (ArrowHeight - Len) / 2; Move(RPort,Left + ArrowWidth - 1 - i - Shift,Start); Draw(RPort,Left + ArrowWidth - 1 - i - Shift,Start + Len - 1); Move(RPort,Left + ArrowWidth - 1 - i + Shift,Start); Draw(RPort,Left + ArrowWidth - 1 - i + Shift,Start + Len - 1); } } } #endif /* DO_TAPEDECK_KIND */ /*****************************************************************************/ #ifdef DO_TAPEDECK_KIND STATIC VOID __regargs LTK_DrawPrevNext(struct RastPort *RPort,BOOLEAN Prev,LONG Left,LONG Top,LONG Width,LONG Height) { LONG i,Len,Start,ArrowWidth,ArrowHeight,LineWidth; LineWidth = (Width + 15) / 16; ArrowWidth = Width; ArrowHeight = Height; Left = Left - (LineWidth / 2); if(Prev) { for(i = 0 ; i < ArrowWidth ; i++) { Len = (ArrowHeight * (i + 1) + ArrowWidth - 1) / ArrowWidth; Start = Top + (ArrowHeight - Len) / 2; Move(RPort,Left + i,Start); Draw(RPort,Left + i,Start + Len - 1); } for(i = 0 ; i < LineWidth ; i++) { Move(RPort,Left + i,Top); Draw(RPort,Left + i,Top + Height - 1); } } else { for(i = 0 ; i < ArrowWidth ; i++) { Len = (ArrowHeight * (i + 1) + ArrowWidth - 1) / ArrowWidth; Start = Top + (ArrowHeight - Len) / 2; Move(RPort,Left + ArrowWidth - 1 - i,Start); Draw(RPort,Left + ArrowWidth - 1 - i,Start + Len - 1); } for(i = 0 ; i < LineWidth ; i++) { Move(RPort,Left + ArrowWidth - 1 - i,Top); Draw(RPort,Left + ArrowWidth - 1 - i,Top + Height - 1); } } } #endif /* DO_TAPEDECK_KIND */ /*****************************************************************************/ STATIC VOID __regargs LTK_DrawPicker(struct RastPort *RPort,BOOLEAN UpDirection,LONG Left,LONG Top,LONG Width,LONG Height) { LONG i,Len,ArrowHeight,ArrowWidth,LineHeight,Start; LineHeight = (Height + 15) / 16; ArrowHeight = Height - (Height + 7) / 8; ArrowWidth = Width; if(UpDirection) { for(i = 0 ; i < ArrowHeight ; i++) { Len = (ArrowWidth * (i + 1) + ArrowHeight - 1) / ArrowHeight; Start = Left + (ArrowWidth - Len) / 2; Move(RPort,Start,Top + i); Draw(RPort,Start + Len - 1,Top + i); } } else { for(i = 0 ; i < ArrowHeight ; i++) { Len = (ArrowWidth * (i + 1) + ArrowHeight - 1) / ArrowHeight; Start = Left + (ArrowWidth - Len) / 2; Move(RPort,Start,Top + ArrowHeight - 1 - i); Draw(RPort,Start + Len - 1,Top + ArrowHeight - 1 - i); } } for(i = 0 ; i < LineHeight ; i++) { Move(RPort,Left,Top + Height - 1 - i); Draw(RPort,Left + Width - 1,Top + Height - 1 - i); } } /*****************************************************************************/ #ifdef DO_TAPEDECK_KIND STATIC VOID __regargs LTK_RenderCircle(struct RastPort *RPort,LONG Left,LONG Top,LONG Radius,LONG AspectX,LONG AspectY) { LONG x = 0,y = Radius,Delta = 2 * (1 - Radius),delta,Limit = 0,Length; while(y >= Limit) { if(Delta < 0) { delta = 2 * Delta + 2 * y - 1; if(delta > 0) { x = x + 1; y = y - 1; Delta = Delta + 2 * x - 2 * y + 2; } else { x = x + 1; Delta = Delta + 2 * x + 1; } } else { if(Delta > 0) { delta = 2 * Delta - 2 * x - 1; if(delta > 0) { y = y - 1; Delta = Delta - 2 * y + 1; } else { x = x + 1; y = y - 1; Delta = Delta + 2 * x - 2 * y + 2; } } else { x = x + 1; y = y - 1; Delta = Delta + 2 * x - 2 * y + 2; } } Length = (x * AspectY) / AspectX; Move(RPort,Left - Length,Top + y - 1); Draw(RPort,Left + Length - 1,Top + y - 1); Move(RPort,Left - Length,Top - y); Draw(RPort,Left + Length - 1,Top - y); } } #endif /* DO_TAPEDECK_KIND */ /*****************************************************************************/ #ifdef DO_TAPEDECK_KIND STATIC VOID __regargs LTK_RenderArrow(struct RastPort *RPort,BOOLEAN LeftDirection,LONG Left,LONG Top,LONG Width,LONG Height) { LONG i,Len,Start; if(LeftDirection) { for(i = 0 ; i < Width ; i++) { Len = (Height * (i + 1) + Width - 1) / Width; Start = Top + (Height - Len) / 2; Move(RPort,Left + i,Start); Draw(RPort,Left + i,Start + Len - 1); } } else { for(i = 0 ; i < Width ; i++) { Len = (Height * (i + 1) + Width - 1) / Width; Start = Top + (Height - Len) / 2; Move(RPort,Left + Width - 1 - i,Start); Draw(RPort,Left + Width - 1 - i,Start + Len - 1); } } } #endif /* DO_TAPEDECK_KIND */ /*****************************************************************************/ #ifdef DO_TAPEDECK_KIND STATIC VOID __regargs LTK_DrawTapeButton(struct RastPort *RPort,ImageInfo *imageInfo,LONG Left,LONG Top,LONG Width,LONG Height,LONG AspectX,LONG AspectY,LONG Background) { LONG SizeX,SizeY,Mid,Size; ImageTypes ImageType; ImageType = imageInfo -> ImageType; SizeX = imageInfo -> GlyphWidth; SizeY = imageInfo -> GlyphHeight; Left += 6; Top += 3; Width -= 2 * 6; Height -= 2 * 3; if(!SizeY) SizeY = Height; if(!SizeX) { SizeX = (SizeY * AspectY) / AspectX; if(ImageType == IMAGECLASS_BACKWARD || ImageType == IMAGECLASS_FORWARD) SizeX *= 2; } if(SizeX > 0 && SizeY > 0) { switch(ImageType) { case IMAGECLASS_BACKWARD: case IMAGECLASS_FORWARD: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; LTK_DrawBackFore(RPort,ImageType == IMAGECLASS_BACKWARD,Left,Top,SizeX,SizeY); break; case IMAGECLASS_PREVIOUS: case IMAGECLASS_NEXT: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; LTK_DrawPrevNext(RPort,ImageType == IMAGECLASS_PREVIOUS,Left,Top,SizeX,SizeY); break; case IMAGECLASS_EJECT: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; LTK_DrawPicker(RPort,TRUE,Left,Top,SizeX,SizeY); break; case IMAGECLASS_RECORD: LTK_RenderCircle(RPort,Left + Width / 2,Top + Height / 2,SizeY / 2,AspectX,AspectY); break; case IMAGECLASS_PLAY: case IMAGECLASS_REWIND: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; LTK_RenderArrow(RPort,ImageType == IMAGECLASS_REWIND,Left,Top,SizeX,SizeY); break; case IMAGECLASS_STOP: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; RectFill(RPort,Left,Top,Left + SizeX - 1,Top + SizeY - 1); break; case IMAGECLASS_PAUSE: Left = Left + (Width - SizeX) / 2; Top = Top + (Height - SizeY) / 2; RectFill(RPort,Left,Top,Left + SizeX - 1,Top + SizeY - 1); Size = SizeX - (2 * SizeX) / 3; Mid = SizeX / 3; LTK_SetAPen(RPort,Background); RectFill(RPort,Left + Mid,Top,Left + Mid + Size - 1,Top + SizeY - 1); break; } } } #endif /* DO_TAPEDECK_KIND */ /*****************************************************************************/ STATIC VOID __regargs LTK_DrawBox(struct RastPort *rp,struct DrawInfo *drawInfo,LONG left,LONG top,LONG width,LONG height,BOOLEAN selected,BOOLEAN ghosted,ImageInfo *imageInfo) { UWORD *pens = drawInfo -> dri_Pens; UWORD pen1,pen2,pen3,pen4; ImageTypes imageType = imageInfo -> ImageType; if(selected) { pen1 = SHADOWPEN; pen2 = SHINEPEN; pen3 = FILLPEN; pen4 = FILLTEXTPEN; } else { pen1 = SHINEPEN; pen2 = SHADOWPEN; pen3 = BACKGROUNDPEN; pen4 = TEXTPEN; } LTK_SetPens(rp,pens[pen1],0,JAM1); Move(rp,left + 1,top + 1); Draw(rp,left + 1,top + height - 2); Draw(rp,left,top + height - 1); Draw(rp,left,top); Draw(rp,left + width - 2,top); LTK_SetAPen(rp,pens[pen2]); Move(rp,left + width - 2,top + height - 2); Draw(rp,left + width - 2,top + 1); Draw(rp,left + width - 1,top); Draw(rp,left + width - 1,top + height - 1); Draw(rp,left + 1,top + height - 1); LTK_SetAPen(rp,pens[pen3]); RectFill(rp,left + 2,top + 1,left + 2 + width - 5,top + 1 + height - 3); LTK_SetAPen(rp,pens[pen4]); switch(imageType) { case IMAGECLASS_PICKER: { LONG Left = left + 4, Top = top + 2, Width = width - 8, Height = height - 4; LTK_DrawPicker(rp,FALSE,Left,Top,Width,Height); break; } case IMAGECLASS_LEFTINCREMENTER: case IMAGECLASS_RIGHTINCREMENTER: LTK_DrawIncrementer(rp,imageType == IMAGECLASS_LEFTINCREMENTER,left + 2,top + 1,width - 4,height - 2); break; #ifdef DO_TAPEDECK_KIND case IMAGECLASS_BACKWARD: case IMAGECLASS_FORWARD: case IMAGECLASS_PREVIOUS: case IMAGECLASS_NEXT: case IMAGECLASS_RECORD: case IMAGECLASS_PLAY: case IMAGECLASS_STOP: case IMAGECLASS_PAUSE: case IMAGECLASS_EJECT: case IMAGECLASS_REWIND: LTK_DrawTapeButton(rp,imageInfo,left,top,width,height,drawInfo -> dri_Resolution . X,drawInfo -> dri_Resolution . Y,pens[pen3]); break; #endif /* DO_TAPEDECK_KIND */ } if(ghosted) { if(width > 4 || height > 2) { LTK_SetAPen(rp,pens[BLOCKPEN]); SetAfPt(rp,(UWORD *)&ghostingPat,1); RectFill(rp,left + 2,top + 1,left + width - 1 - 2,top + height - 1 - 1); SetAfPt(rp,NULL,0); } } } /*****************************************************************************/ STATIC ULONG __regargs LTK_ImageClassDraw(struct Image *image,struct impDraw *drawMsg,ImageInfo *imageInfo) { LTK_DrawBox(drawMsg -> imp_RPort,drawMsg -> imp_DrInfo,image -> LeftEdge + drawMsg -> imp_Offset . X,image -> TopEdge + drawMsg -> imp_Offset . Y,image -> Width,image -> Height,drawMsg -> imp_State == IDS_SELECTED,drawMsg -> imp_State == IDS_DISABLED,imageInfo); return(TRUE); } /*****************************************************************************/ STATIC ULONG __regargs LTK_ImageClassErase(struct Image *image,struct impErase *eraseMsg) { LONG left; LONG top; left = eraseMsg -> imp_Offset . X + image -> LeftEdge; top = eraseMsg -> imp_Offset . Y + image -> TopEdge; LTK_SetAPen(eraseMsg -> imp_RPort,0); RectFill(eraseMsg -> imp_RPort,left,top,left + image -> Width - 1,top + image -> Height - 1); return(TRUE); } /*****************************************************************************/ STATIC ULONG __regargs LTK_ImageClassNew(struct IClass *class,Object *object,struct opSet *SetMethod) { struct TagItem *Tag; if(Tag = FindTagItem(IIA_ImageType,SetMethod -> ops_AttrList)) { struct Image *NewImage; if(NewImage = (struct Image *)DoSuperMethodA(class,object,(Msg)SetMethod)) { struct ImageInfo *MoreInfo = INST_DATA(class,NewImage); MoreInfo -> ImageType = Tag -> ti_Data; MoreInfo -> GlyphWidth = GetTagData(IIA_GlyphWidth,0,SetMethod -> ops_AttrList); MoreInfo -> GlyphHeight = GetTagData(IIA_GlyphHeight,0,SetMethod -> ops_AttrList); return((ULONG)NewImage); } } return(NULL); } /*****************************************************************************/ STATIC ULONG __saveds __asm LTK_ImageDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg) { switch(msg -> MethodID) { case IM_ERASE: return(LTK_ImageClassErase((struct Image *)object,(struct impErase *)msg)); case IM_DRAW: return(LTK_ImageClassDraw((struct Image *)object,(struct impDraw *)msg,(ImageInfo *)INST_DATA(class,object))); case OM_NEW: return(LTK_ImageClassNew(class,object,(struct opSet *)msg)); default: return(DoSuperMethodA(class,object,msg)); } } /*****************************************************************************/ STATIC VOID __regargs LTK_TunnelDraw(struct RastPort *rp,LONG from,LONG to,LONG y,LONG left,LONG right) { Draw(rp,from,y); Draw(rp,left - 1,y); Move(rp,right + 1,y); Draw(rp,to,y); } /*****************************************************************************/ STATIC VOID __regargs LTK_DrawGroove(LayoutHandle *handle,LONG left,LONG top,LONG width,LONG height,LONG from,LONG to) { struct RastPort *rp = &handle -> RPort; LTK_SetAPen(rp,handle -> ShadowPen); Move(rp,left + 1,top + 1); Draw(rp,left + 1,top + height - 2); Draw(rp,left,top + height - 1); LTK_TunnelDraw(rp,left,left + width - 2,top,from,to); Draw(rp,left + width - 4,top + 2); Draw(rp,left + width - 4,top + height - 3); Move(rp,left + width - 3,top + 2); Draw(rp,left + width - 3,top + height - 2); Draw(rp,left + 3,top + height - 2); LTK_SetAPen(rp,handle -> ShinePen); Move(rp,left + width - 2,top + height - 2); Draw(rp,left + width - 2,top + 1); Draw(rp,left + width - 1,top); Draw(rp,left + width - 1,top + height - 1); Draw(rp,left + 1,top + height - 1); Draw(rp,left + 3,top + height - 3); Draw(rp,left + 3,top + 2); Move(rp,left + 2,top + height - 3); LTK_TunnelDraw(rp,left + 2,left + width - 4,top + 1,from,to); } /*****************************************************************************/ STATIC VOID __regargs LTK_DrawLabel(LayoutHandle *handle,ObjectNode *label) { struct RastPort *rp; LONG left; left = label -> Left + (label -> Width - label -> LabelWidth) / 2; rp = &handle -> RPort; LockLayerRom(rp -> Layer); LTK_DrawGroove(handle,label -> Left + handle -> GlyphWidth / 2,label -> Top + handle -> RPort . TxHeight / 2,label -> Width - handle -> GlyphWidth,label -> Height - (handle -> RPort . TxHeight + handle -> InterHeight) / 2,left,left + label -> LabelWidth - 1); LTK_SetPens(rp,handle -> DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN],0,JAM1); LTK_PlaceText(handle,label -> Label,strlen(label -> Label),left + handle -> GlyphWidth,label -> Top + handle -> RPort . TxBaseline); UnlockLayerRom(rp -> Layer); } /*****************************************************************************/ STATIC APTR __regargs LTK_Alloc(LayoutHandle *handle,ULONG amount) { APTR result = NULL; if(!handle -> Failed) { result = AsmAllocPooled(handle -> Pool,amount,SysBase); if(!result) handle -> Failed = TRUE; } return(result); } /*****************************************************************************/ STATIC VOID __regargs LTK_Free(LayoutHandle *handle,APTR mem,ULONG memsize) { if(mem) AsmFreePooled(handle -> Pool,mem,memsize,SysBase); } /*****************************************************************************/ STATIC VOID __regargs LTK_DetermineSize(LayoutHandle *Handle,ObjectNode *Node) { if(!Handle -> Failed) { LONG i,Len,Width,Max; if(Node -> Label) Node -> LabelWidth = LT_LabelWidth(Handle,Node -> Label); else Node -> LabelWidth = 0; switch(Node -> Type) { case GROUP_KIND: LTK_LayoutGroup(Handle,Node); break; case XBAR_KIND: Node -> Width = Handle -> GlyphWidth; Node -> Height = 6; break; case YBAR_KIND: Node -> Width = 6; Node -> Height = Handle -> RPort . TxHeight; break; case FRAME_KIND: if(Node -> Special . Frame . DrawBox) { Node -> Width = 4 + Node -> Special . Frame . InnerWidth + 4; Node -> Height = 2 + Node -> Special . Frame . InnerHeight + 2; } else { Node -> Width = Node -> Special . Frame . InnerWidth; Node -> Height = Node -> Special . Frame . InnerHeight; } break; case BOX_KIND: Node -> LabelWidth = 0; if(Node -> Special . Box . Labels) { for(i = 0 ; i < Node -> Lines ; i++) { if((Width = TextLength(&Handle -> RPort,Node -> Special . Box . Labels[i],strlen(Node -> Special . Box . Labels[i]))) > Node -> LabelWidth) Node -> LabelWidth = Width; } } Max = Node -> Chars; if(Node -> Special . Box . Lines) { LONG MaxWidth = 0; for(i = 0 ; i < Node -> Lines ; i++) { if(Node -> Special . Box . Lines[i]) { if(Len = strlen(Node -> Special . Box . Lines[i])) { if((Width = TextLength(&Handle -> RPort,Node -> Special . Box . Lines[i],Len)) > MaxWidth) MaxWidth = Width; } } } if(Max < (MaxWidth + Handle -> GlyphWidth - 1) / Handle -> GlyphWidth) Max = (MaxWidth + Handle -> GlyphWidth - 1) / Handle -> GlyphWidth; } Node -> Height = 2 + Node -> Lines * Handle -> RPort . TxHeight + 2; Node -> Width = 4 + Max * Handle -> GlyphWidth + 4; break; case BUTTON_KIND: if(Node -> Chars * Handle -> GlyphWidth > Node -> LabelWidth) Node -> Width = Node -> Chars * Handle -> GlyphWidth; else Node -> Width = Node -> LabelWidth; Node -> LabelWidth = 0; Node -> LabelPlace = PLACE_IN; if(Node -> Special . Button . ExtraFat) { Node -> Width = 6 + Handle -> GlyphWidth + Node -> Width + Handle -> GlyphWidth + 6; Node -> Height = 2 + (3 * Handle -> RPort . TxHeight) / 2 + 2; } else { Node -> Width = 6 + Node -> Width + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; } break; case CHECKBOX_KIND: Node -> Width = Node -> Height = (3 * Handle -> RPort . TxHeight) / 2; if(!V39) { if(Node -> Width < CHECKBOX_WIDTH) Node -> Width = CHECKBOX_WIDTH; if(Node -> Height < CHECKBOX_HEIGHT) Node -> Height = CHECKBOX_HEIGHT; } else { Node -> Width = (Node -> Width * Handle -> AspectY) / Handle -> AspectX; if(Node -> Height < CHECKBOX_HEIGHT) { Node -> Height = CHECKBOX_HEIGHT; Node -> Width = (Node -> Height * Handle -> AspectY) / Handle -> AspectX; } } break; case LISTVIEW_KIND: i = 0; Max = 0; Width = Node -> Chars * Handle -> GlyphWidth; if(Node -> Special . List . Labels) { struct Node *Item; SCANLIST(Node -> Special . List . Labels,Item) { i++; if((Len = TextLength(&Handle -> RPort,Item -> ln_Name,strlen(Item -> ln_Name))) > Max) Max = Len; } } Node -> Max = i - 1; if(Max > Width) { Width = Max; Node -> Chars = Width / Handle -> GlyphWidth; } if(!V39) Node -> Width = (4 + Width + 4) + (2 + 2 * Handle -> GlyphWidth + 2) + 8; else Node -> Width = (4 + Width + 4) + (2 + 2 * Handle -> GlyphWidth + 2); Node -> Height = 2 + Node -> Lines * Handle -> RPort . TxHeight + 2; if(Node -> Special . List . ReadOnly) { if(Node -> Special . List . LinkID != -1) { if(!V39) Node -> Height += 2 + Handle -> RPort . TxHeight + 2; } } else { if(Node -> Special . List . LinkID != -1 && Node -> Special . List . LinkID != NIL_LINK) Node -> Height += 3 + Handle -> RPort . TxHeight + 3; } if(Node -> Special . List . ExtraLabels) { for(i = Max = 0 ; Node -> Special . List . ExtraLabels[i] ; i++) { if((Len = TextLength(&Handle -> RPort,Node -> Special . List . ExtraLabels[i],strlen(Node -> Special . List . ExtraLabels[i]))) > Max) Max = Len; } Node -> Special . List . ExtraLabelWidth = Max; } if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case MX_KIND: i = 0; Max = 0; while(Node -> Special . Radio . Choices[i]) { if((Width = TextLength(&Handle -> RPort,Node -> Special . Radio . Choices[i],strlen(Node -> Special . Radio . Choices[i]))) > Max) Max = Width; i++; } Node -> Max = i - 1; Node -> Special . Radio . LabelWidth = Max; Node -> Height = MAX(MX_HEIGHT,Handle -> RPort . TxHeight); if(!V39) Node -> Width = MX_WIDTH; else { Node -> Width = (Node -> Height * Handle -> AspectY) / Handle -> AspectX; if(Node -> Height < MX_HEIGHT) { Node -> Height = MX_HEIGHT; Node -> Width = (Node -> Height * Handle -> AspectX) / Handle -> AspectY; } } Node -> Lines = i; Node -> Height = Node -> Lines * (Node -> Height + Handle -> InterHeight) - Handle -> InterHeight; break; case TEXT_KIND: if(Node -> Special . Text . Text) Max = TextLength(&Handle -> RPort,Node -> Special . Text . Text,strlen(Node -> Special . Text . Text)); else Max = 0; Width = Node -> Chars * Handle -> GlyphWidth; if(Max > Width) Width = Max; Node -> Width = 6 + Width + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; if(Node -> Special . Text . UsePicker) Node -> Width += (Node -> Height * Handle -> AspectY) / Handle -> AspectX; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; #ifdef DO_GAUGE_KIND case GAUGE_KIND: Width = TextLength(&Handle -> RPort,"0% 100%",7); if(Handle -> GlyphWidth * Node -> Chars > Width) Width = Handle -> GlyphWidth * Node -> Chars; Node -> Width = 6 + Width + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 2 + Handle -> InterHeight + Handle -> RPort . TxHeight + 3; if(Node -> Label) Node -> LabelWidth = LT_LabelWidth(Handle,Node -> Label); else Node -> LabelWidth = 0; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: { LONG Width,Height; Width = TextLength(&Handle -> RPort,"AA",2); if(Width < 2 * Handle -> GlyphWidth); Width = 2 * Handle -> GlyphWidth; if(Width < 2 * Handle -> RPort . TxHeight) Width = 2 * Handle -> RPort . TxHeight; if(Node -> Special . TapeDeck . Smaller) Width = (3 * Width) / 4; if(Width & 1) Width++; Width = 1 + ((Width + 5) / 6) * 6; Height = (Handle -> AspectX * Width) / (Handle -> AspectY * 2); if(!(Height & 1)) Height++; if(Node -> Special . TapeDeck . ButtonType == TDBT_BACKWARD || Node -> Special . TapeDeck . ButtonType == TDBT_FORWARD) Node -> Special . TapeDeck . ButtonWidth = Width; else Node -> Special . TapeDeck . ButtonWidth = Width / 2; Node -> Special . TapeDeck . ButtonHeight = Height; if(Handle -> GlyphWidth * Node -> Chars > Width) Width = Handle -> GlyphWidth * Node -> Chars; Node -> Width = 6 + Width + 6; Node -> Height = 3 + Height + 3; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; } #endif /* DO_TAPEDECK_KIND */ case NUMBER_KIND: Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 2 + Handle -> RPort . TxHeight + 2; break; case CYCLE_KIND: Width = Node -> Chars * Handle -> GlyphWidth; if(Node -> Special . Cycle . Choices) { for(i = 0 ; Node -> Special . Cycle . Choices[i] ; i++) { if((Len = TextLength(&Handle -> RPort,Node -> Special . Cycle . Choices[i],strlen(Node -> Special . Cycle . Choices[i]))) > Width) Width = Len; } Node -> Max = i - 1; } Node -> Width = 26 + Width + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case PALETTE_KIND: if(Node -> Special . Palette . NumColours) Node -> Max = Node -> Min + Node -> Special . Palette . NumColours - 1; else { if(!Node -> Special . Palette . Depth) Node -> Special . Palette . Depth = 1; Node -> Special . Palette . NumColours = 1L << Node -> Special . Palette . Depth; Node -> Max = Node -> Min + Node -> Special . Palette . NumColours - 1; } if(Node -> Special . Palette . SmallPalette) { Node -> Width = Handle -> GlyphWidth * (Node -> Max - Node -> Min + 1); Node -> Height = 1 + Handle -> RPort . TxHeight + 1; } else { Node -> Width = 2 * Handle -> GlyphWidth * (Node -> Max - Node -> Min + 1); Node -> Height = 2 * Handle -> RPort . TxHeight; } if(Node -> Chars * Handle -> GlyphWidth > Node -> Width) Node -> Width = Node -> Chars * Handle -> GlyphWidth; if(Node -> Special . Palette . NumColours > 16) { Node -> Height *= 2; Node -> Width /= 2; } if(Node -> Lines) { if(!Node -> Chars) Node -> Width = Handle -> GlyphWidth; else Node -> Width = Node -> Chars * Handle -> GlyphWidth; Node -> Height = Node -> Lines * Handle -> RPort . TxHeight; } break; case SCROLLER_KIND: if(Node -> Special . Scroller . Vertical) { if(Node -> Special . Scroller . Thin) Node -> Width = 6 + Handle -> GlyphWidth + 6; else Node -> Width = 6 + (3 * Handle -> GlyphWidth) / 2 + 6; Node -> Height = 2 + Node -> Lines * Handle -> RPort . TxHeight; if(Node -> Special . Scroller . Arrows) { WORD ScrollerHeight = (Handle -> AspectX * Node -> Width) / Handle -> AspectY; if(Node -> Height < 2 + Node -> Lines * Handle -> RPort . TxHeight + 2 * ScrollerHeight) Node -> Height = 2 + Node -> Lines * Handle -> RPort . TxHeight + 2 * ScrollerHeight; Node -> Special . Scroller . ArrowSize = ScrollerHeight; } } else { Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 2 + Handle -> RPort . TxHeight; if(Node -> Special . Scroller . Arrows) { WORD ScrollerWidth = (Handle -> AspectY * Node -> Height) / Handle -> AspectX; if(Node -> Width < 6 + Handle -> GlyphWidth + 2 * ScrollerWidth + 6) Node -> Width = 6 + Handle -> GlyphWidth + 2 * ScrollerWidth + 6; Node -> Special . Scroller . ArrowSize = ScrollerWidth; } } if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case SLIDER_KIND: Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 2 + Handle -> RPort . TxHeight + 1; LT_LevelWidth(Handle,Node -> Special . Slider . LevelFormat,Node -> Special . Slider . DispFunc,Node -> Min,Node -> Max,&Node -> Special . Slider . LevelWidth,&Node -> Special . Slider . MaxLevelLen,Node -> Special . Slider . FullLevelCheck); if(!V40) { if(Node -> Special . Slider . MaxLevelLen * Handle -> RPort . TxWidth < Node -> Special . Slider . LevelWidth) Node -> Special . Slider . MaxLevelLen = (Node -> Special . Slider . LevelWidth + Handle -> RPort . TxWidth - 1) / Handle -> RPort . TxWidth; } if(Node -> Special . Slider . LevelPlace == PLACETEXT_LEFT && Node -> Label) { LONG space,len; STRPTR Buffer; space = TextLength(&Handle -> RPort," ",1); space = (Node -> Special . Slider . LevelWidth + space - 1) / space; if(!V40 && (Handle -> RPort . TxFlags & FPF_PROPORTIONAL)) { Node -> Special . Slider . MaxLevelLen++; space++; } if(Node -> Special . Slider . OriginalLabel) LTK_Free(Handle,Node -> Label,strlen(Node -> Label) + 1); else Node -> Special . Slider . OriginalLabel = Node -> Label; len = strlen(Node -> Special . Slider . OriginalLabel); if(Buffer = LTK_Alloc(Handle,len + space + 1)) { strcpy(Buffer,Node -> Special . Slider . OriginalLabel); while(space > 0) { Buffer[len] = ' '; len++; space--; } Buffer[len] = 0; Node -> Label = Buffer; Node -> LabelWidth = LT_LabelWidth(Handle,Node -> Label); } else break; } if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case STRING_KIND: Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; if(Node -> Special . String . UsePicker) Node -> Width += (Node -> Height * Handle -> AspectY) / Handle -> AspectX; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case INTEGER_KIND: Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; if(Node -> Special . Integer . UseIncrementers) { Node -> Width += (Node -> Height * 4) / 5; Node -> Width += (Node -> Height * 4) / 5; } if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; case PASSWORD_KIND: case FRACTION_KIND: Node -> Width = 6 + Node -> Chars * Handle -> GlyphWidth + 6; Node -> Height = 3 + Handle -> RPort . TxHeight + 3; if(Node -> LabelWidth > Node -> Width && (Node -> LabelPlace == PLACE_ABOVE || Node -> LabelPlace == PLACE_BELOW)) Node -> Width = Node -> LabelWidth; break; } } } /*****************************************************************************/ STATIC ULONG __asm __saveds LTK_DefaultHistoryHook(register __a0 struct Hook *Hook,register __a1 STRPTR NewString,register __a2 struct Gadget *Gadget) { ObjectNode *Node = (ObjectNode *)Gadget -> UserData; struct LayoutHandle *Handle = Node -> Special . String . LayoutHandle; struct MinList *List = (struct MinList *)Hook -> h_Data; if(NewString) { ULONG *Data; if(Data = (ULONG *)LTK_Alloc(Handle,sizeof(ULONG) + sizeof(struct Node) + strlen(NewString) + 1)) { struct Node *NewNode; *Data++ = sizeof(ULONG) + sizeof(struct Node) + strlen(NewString) + 1; NewNode = (struct Node *)Data; NewNode -> ln_Name = (STRPTR)(NewNode + 1); strcpy(NewNode -> ln_Name,NewString); AddTail((struct List *)List,NewNode); } else return(FALSE); } else { if(List -> mlh_Head -> mln_Succ) { ULONG *Data = (ULONG *)RemHead((struct List *)List); LTK_Free(Handle,&Data[-1],Data[-1]); } } return(TRUE); } /*****************************************************************************/ STATIC VOID __regargs LTK_Spread(LayoutHandle *Handle,ObjectNode *Group,LONG Width,LONG Height) { ObjectNode *Node; LONG Count; Count = 0; SCANGROUP(Group,Node) { Count++; } if(Group -> Special . Group . Horizontal) { LONG Room = Width - Group -> Width,Left,Width,i = 0; if(Count > 1) { Left = 0; Room += --Count * Handle -> InterWidth; } else Left = Room / 2; SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { Width = Node -> Width; switch(Node -> LabelPlace) { case PLACE_LEFT: if(Node -> Type == MX_KIND) { Left += Node -> Special . Radio . LabelWidth + INTERWIDTH; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) Left += Node -> LabelWidth + INTERWIDTH; else Width += INTERWIDTH + Node -> LabelWidth; } } else Left += Node -> LabelWidth + INTERWIDTH; break; case PLACE_RIGHT: if(Node -> Type == MX_KIND) { Width += INTERWIDTH + Node -> Special . Radio . LabelWidth; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) Left += Node -> LabelWidth + INTERWIDTH; else Width += INTERWIDTH + Node -> LabelWidth; } } else Width += INTERWIDTH + Node -> LabelWidth; break; } if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . ExtraLabelWidth) Left += Node -> Special . List . ExtraLabelWidth + INTERWIDTH; if(Node -> Type == SLIDER_KIND && Node -> Special . Slider . LevelPlace == PLACETEXT_RIGHT) Width += INTERWIDTH + Node -> Special . Slider . LevelWidth; Node -> Left = Left; Left += Width + ((Room * (i + 1)) / Count - (Room * i) / Count); i++; } } } else { LONG Room = Height - Group -> Height,Height,Top,y,i = 0; if(Count > 1) { Top = 0; Room += --Count * Handle -> InterHeight; } else Top = Room / 2; SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { if(Count++) { if(Node -> ExtraSpace > 0) y = Top + Node -> ExtraSpace * Handle -> InterHeight; else { if(Node -> ExtraSpace < 0) y = Top - Node -> ExtraSpace; else y = Top + Handle -> InterHeight; } } else y = Top; if(Node -> LabelPlace == PLACE_ABOVE) y += Handle -> RPort . TxHeight + INTERHEIGHT; Node -> Top = y; if(Node -> LabelPlace == PLACE_BELOW && Node -> Label) Height = Node -> Height + INTERHEIGHT + Handle -> RPort . TxHeight; else Height = Node -> Height; Top = y + Height + ((Room * (i + 1)) / Count - (Room * i) / Count); i++; } } } } /*****************************************************************************/ STATIC VOID __regargs LTK_LayoutGroup(LayoutHandle *Handle,ObjectNode *Group) { if(!Handle -> Failed) { ObjectNode *Node; ObjectNode *ReturnKey; ObjectNode *EscKey; ObjectNode *CursorKey; LONG Left; LONG Top; LONG Width; LONG Height; Left = 0; Top = 0; ReturnKey = NULL; EscKey = NULL; CursorKey = NULL; if(Group -> Special . Group . SameSize) { LONG MaxWidth = 0; LONG MaxHeight = 0; SCANGROUP(Group,Node) { LTK_DetermineSize(Handle,Node); if(Node -> Type == BUTTON_KIND) { if(Node -> Special . Button . ReturnKey) ReturnKey = Node; else { if(Node -> Special . Button . EscKey) EscKey = Node; } } if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . CursorKey) CursorKey = Node; if(Node -> Width > MaxWidth) MaxWidth = Node -> Width; if(Node -> Height > MaxHeight) MaxHeight = Node -> Height; } if(ReturnKey) { SCANGROUP(Group,Node) { Node -> GroupIndent = TRUE; Node -> Width += 4 + 4; Node -> Height += 2 + 2; if(Node -> Width > MaxWidth) MaxWidth = Node -> Width; if(Node -> Height > MaxHeight) MaxHeight = Node -> Height; } } SCANGROUP(Group,Node) { if(Node -> Width < MaxWidth) { if(Node -> Type == GROUP_KIND) Node -> Special . Group . ExtraLeft += (MaxWidth - Node -> Width) / 2; Node -> Width = MaxWidth; } if(Node -> Height < MaxHeight) { if(Node -> Type == GROUP_KIND) Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2; Node -> Height = MaxHeight; } } } else { SCANGROUP(Group,Node) { LTK_DetermineSize(Handle,Node); if(Node -> Type == BUTTON_KIND) { if(Node -> Special . Button . ReturnKey) ReturnKey = Node; else { if(Node -> Special . Button . EscKey) EscKey = Node; } } if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . CursorKey) CursorKey = Node; } if(ReturnKey) { SCANGROUP(Group,Node) { Node -> GroupIndent = TRUE; Node -> Width += 4 + 4; Node -> Height += 2 + 2; } } } if(Group -> Special . Group . Horizontal) { LONG x,y,w,MaxTop = 0,MaxWidth = 0,MaxHeight = 0,Count = 0; if(Group -> Node . mln_Pred -> mln_Pred && Group -> Special . Group . LastAttributes) { ObjectNode *LastGroup = (ObjectNode *)Group -> Node . mln_Pred; MaxTop = LastGroup -> Special . Group . MaxOffset; MaxHeight = LastGroup -> Special . Group . MaxSize; } SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { if(!Group -> Special . Group . Paging && Count++) { if(Node -> ExtraSpace > 0) x = Left + Node -> ExtraSpace * Handle -> InterWidth; else { if(Node -> ExtraSpace < 0) x = Left - Node -> ExtraSpace; else x = Left + Handle -> InterWidth; } } else x = Left; y = Top; w = Node -> Width; switch(Node -> LabelPlace) { case PLACE_LEFT: if(Node -> Type == MX_KIND) { x += Node -> Special . Radio . LabelWidth + INTERWIDTH; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) x += Node -> LabelWidth + INTERWIDTH; else w += INTERWIDTH + Node -> LabelWidth; } } else { if(Node -> Label || Node -> Type == BOX_KIND) x += Node -> LabelWidth + INTERWIDTH; } break; case PLACE_RIGHT: if(Node -> Type == MX_KIND) { w += INTERWIDTH + Node -> Special . Radio . LabelWidth; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) x += Node -> LabelWidth + INTERWIDTH; else w += INTERWIDTH + Node -> LabelWidth; } } else { if(Node -> Label || Node -> Type == BOX_KIND) w += INTERWIDTH + Node -> LabelWidth; } break; case PLACE_ABOVE: if(Node -> Label || Node -> Type == BOX_KIND) y += Handle -> RPort . TxHeight + INTERHEIGHT; break; case PLACE_BELOW: break; case PLACE_IN: break; } if(Node -> Type == SLIDER_KIND && Node -> Special . Slider . LevelPlace == PLACETEXT_RIGHT) w += INTERWIDTH + Node -> Special . Slider . LevelWidth; if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . ExtraLabelWidth) x += Node -> Special . List . ExtraLabelWidth + INTERWIDTH; if(y > MaxTop) MaxTop = y; if(Node -> Height > MaxHeight) MaxHeight = Node -> Height; if(Node -> LabelPlace == PLACE_BELOW && Node -> Label) { LONG Height = Node -> Height + INTERHEIGHT + Handle -> RPort . TxHeight; if(Height > MaxHeight) MaxHeight = Height; } else { if(Node -> Height > MaxHeight) MaxHeight = Node -> Height; } if(x + w > MaxWidth) MaxWidth = x+w; Node -> Left = x; if(!Group -> Special . Group . Paging) Left = x + w; } } SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { Node -> Top = MaxTop; if(Node -> Height < MaxHeight) { if(Node -> Type == LISTVIEW_KIND || Node -> Type == PALETTE_KIND) Node -> Height = MaxHeight; else { if(Node -> Type == GROUP_KIND) { if(Node -> Special . Group . Spread) LTK_Spread(Handle,Node,Node -> Width,MaxHeight); else Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2; /* !FIX! */ Node -> Height = MaxHeight; } } } } } Group -> Special . Group . MaxOffset = MaxTop; Group -> Special . Group . MaxSize = MaxHeight; if(Group -> Special . Group . Paging) Width = MaxWidth; else Width = Left; Height = MaxTop + MaxHeight; } else { LONG x,y,w,MaxLeft = 0,MaxWidth = 0,MaxHeight = 0,Count = 0; if(Group -> Node . mln_Pred -> mln_Pred && Group -> Special . Group . LastAttributes) { ObjectNode *LastGroup = (ObjectNode *)Group -> Node . mln_Pred; MaxLeft = LastGroup -> Special . Group . MaxOffset; MaxWidth = LastGroup -> Special . Group . MaxSize; } SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { if(!Group -> Special . Group . Paging && Count++) { if(Node -> ExtraSpace > 0) y = Top + Node -> ExtraSpace * Handle -> InterHeight; else { if(Node -> ExtraSpace < 0) y = Top - Node -> ExtraSpace; else y = Top + Handle -> InterHeight; } } else y = Top; w = Node -> Width; x = Left; switch(Node -> LabelPlace) { case PLACE_LEFT: if(Node -> Type == MX_KIND) { x += Node -> Special . Radio . LabelWidth + INTERWIDTH; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) x += Node -> LabelWidth + INTERWIDTH; } } else { if(Node -> Label || Node -> Type == BOX_KIND) x += Node -> LabelWidth + INTERWIDTH; } break; case PLACE_RIGHT: if(Node -> Type == MX_KIND) { w += INTERWIDTH + Node -> Special . Radio . LabelWidth; if(Node -> Label) { if(Node -> Special . Radio . TitlePlace == PLACETEXT_LEFT) x += Node -> LabelWidth + INTERWIDTH; else w += INTERWIDTH + Node -> LabelWidth; } } else { if(Node -> Label || Node -> Type == BOX_KIND) w += INTERWIDTH + Node -> LabelWidth; } break; case PLACE_ABOVE: if(Node -> Label || Node -> Type == BOX_KIND) y += Handle -> RPort . TxHeight + INTERHEIGHT; break; case PLACE_BELOW: break; case PLACE_IN: break; } if(Node -> Type == SLIDER_KIND && Node -> Special . Slider . LevelPlace == PLACETEXT_RIGHT) w += INTERWIDTH + Node -> Special . Slider . LevelWidth; if(Node -> Type == LISTVIEW_KIND && Node -> Special . List . ExtraLabelWidth) x += Node -> Special . List . ExtraLabelWidth + INTERWIDTH; if(x > MaxLeft) MaxLeft = x; if(w > MaxWidth) MaxWidth = w; if(y + Node -> Height > MaxHeight) MaxHeight = y + Node -> Height; Node -> Top = y; if(!Group -> Special . Group . Paging) Top = y + Node -> Height; if(Node -> LabelPlace == PLACE_BELOW && Node -> Label) Top += INTERHEIGHT + Handle -> RPort . TxHeight; } } SCANGROUP(Group,Node) { if(!LIKE_STRING_KIND(Node) || Node -> Special . String . LinkID == -1) { Node -> Left = MaxLeft; if(Node -> Type == GROUP_KIND && Group -> Special . Group . Paging) Node -> Special . Group . ExtraTop += (MaxHeight - Node -> Height) / 2; if(Node -> Width < MaxWidth) { if(Node -> Type == GROUP_KIND) { if(Node -> Special . Group . Spread) LTK_Spread(Handle,Node,MaxWidth,Node -> Height); else Node -> Special . Group . ExtraLeft += (MaxWidth - Node -> Width) / 2; Node -> Width = MaxWidth; } else { if(Node -> Type == LISTVIEW_KIND || Node -> Type == TEXT_KIND || Node -> Type == GAUGE_KIND || Node -> Type == NUMBER_KIND || Node -> Type == CYCLE_KIND || Node -> Type == PALETTE_KIND || LIKE_STRING_KIND(Node) || Node -> Type == INTEGER_KIND || Node -> Type == BUTTON_KIND || Node -> Type == SLIDER_KIND || Node -> Type == BOX_KIND || Node -> Type == SCROLLER_KIND) { if(Node -> Label && Node -> LabelPlace == PLACE_RIGHT) Node -> Width = MaxWidth - (INTERWIDTH + Node -> LabelWidth); else Node -> Width = MaxWidth; } else { if(Node -> Type == SLIDER_KIND) { if(Node -> Special . Slider . LevelPlace == PLACE_RIGHT) { if(Node -> Width + Node -> Special . Slider . LevelWidth + INTERWIDTH < MaxWidth) Node -> Width = MaxWidth - (Node -> Special . Slider . LevelWidth + INTERWIDTH); } else Node -> Width = MaxWidth; } } } } } } Group -> Special . Group . MaxOffset = MaxLeft; Group -> Special . Group . MaxSize = MaxWidth; if(Group -> Special . Group . Paging) Height = MaxHeight; else Height = Top; Width = MaxLeft + MaxWidth; } Group -> Left = 0; Group -> Top = 0; Group -> Width = Width; Group -> Height = Height; if(Group -> Label) { Group -> LabelWidth = LT_LabelWidth(Handle,Group -> Label) + 2 * Handle -> GlyphWidth; if(Group -> LabelWidth > Group -> Width) { Group -> Special . Group . ExtraLeft += (Group -> LabelWidth - Group -> Width) / 2; Group -> Width = Group -> LabelWidth; } Group -> Width += 2 * (Handle -> GlyphWidth + Handle -> InterWidth) + 8; Group -> Height += Handle -> RPort . TxHeight + 2 * Handle -> InterHeight + 3; } if(ReturnKey) Handle -> ReturnKey = ReturnKey; if(EscKey) Handle -> EscKey = EscKey; if(CursorKey) Handle -> CursorKey = CursorKey; } } /*****************************************************************************/ STATIC VOID __regargs LTK_PlaceGroups(LayoutHandle *handle,ObjectNode *group,LONG left,LONG top) { if(!handle -> Failed) { ObjectNode *node; LONG plusLeft, plusTop, lastSpace; if(group -> Label) { plusLeft = 4 + handle -> GlyphWidth + handle -> InterWidth + group -> Special . Group . ExtraLeft; plusTop = handle -> RPort . TxHeight + handle -> InterHeight + group -> Special . Group . ExtraTop; } else { plusLeft = group -> Special . Group . ExtraLeft; plusTop = group -> Special . Group . ExtraTop; } if(group -> ExtraSpace) { if(group -> Special . Group . ParentGroup -> Special . Group . Horizontal) left += handle -> InterWidth; else top += handle -> InterHeight; } group -> Left = left; group -> Top = top; left += plusLeft; top += plusTop; if(group -> Special . Group . Horizontal) { lastSpace = left; SCANGROUP(group,node) { if(node -> Type == GROUP_KIND) LTK_PlaceGroups(handle,node,lastSpace,top); else { node -> Left += left; node -> Top += top; handle -> Count++; } if(!group -> Special . Group . Paging) { lastSpace = node -> Left + node -> Width + handle -> InterWidth; if(node -> Type == MX_KIND) { if((node -> LabelPlace == PLACETEXT_RIGHT) || (node -> LabelPlace == PLACETEXT_LEFT)) lastSpace += INTERWIDTH + node -> Special . Radio . LabelWidth; } } if(node -> Centered) { // !!! needs to be smarter about object height,dealing with labels,and the like node -> Top = group -> Top + ((group -> Height - node -> Height) / 2); } } } else { lastSpace = top; SCANGROUP(group,node) { if(node -> Type == GROUP_KIND) LTK_PlaceGroups(handle,node,left,lastSpace); else { node -> Left += left; node -> Top += top; handle -> Count++; } if(!group -> Special . Group . Paging) lastSpace = node -> Top + node -> Height + handle -> InterHeight; if(node -> Centered) { // !!! needs to be smarter about object widths,like for MX_KIND node -> Left = group -> Left + ((group -> Width - node -> Width) / 2); } } } } } /*****************************************************************************/ STATIC ObjectNode * __regargs LTK_FindNode_Position(ObjectNode *group,LONG x,LONG y) { ObjectNode *node; SCANGROUP(group,node) { if(node -> Type == GROUP_KIND) { ObjectNode *result; if(result = LTK_FindNode_Position(node,x,y)) return(result); } else { if(node -> Left <= x && node -> Left + node -> Width > x && node -> Top <= y && node -> Top + node -> Height > y) { if(node -> Type == PICKER_KIND) return(node -> Special . Picker . Parent -> UserData); if(node -> Type == INCREMENTER_KIND) return(node -> Special . Incrementer . Parent -> UserData); return(node); } } } return(NULL); } /*****************************************************************************/ STATIC ObjectNode * __regargs LTK_FindNode(ObjectNode *group,LONG id) { ObjectNode *node; ObjectNode *result; SCANGROUP(group,node) { if(node -> Type == GROUP_KIND) { if(node -> ID == id) return(node); if(result = LTK_FindNode(node,id)) return(result); } else { if((node -> ID == id) && (node -> Type != PICKER_KIND) && (node -> Type != INCREMENTER_KIND)) return(node); } } return(NULL); } /*****************************************************************************/ STATIC struct Gadget * __regargs LTK_FindGadget(LayoutHandle *handle,LONG id) { if(handle && handle -> GadgetArray) { LONG i = handle -> Count; while(i--) { if(handle -> GadgetArray[i]) { if(handle -> GadgetArray[i] -> GadgetID == id && handle -> GadgetArray[i] -> UserData) { register struct ObjectNode *Node = (struct ObjectNode *)handle -> GadgetArray[i] -> UserData; if(Node -> PointBack == Node && Node -> Host == handle -> GadgetArray[i]) return(handle -> GadgetArray[i]); } } } } return(NULL); } /*****************************************************************************/ #ifdef DO_PICKSHORTCUTS STATIC VOID __regargs LTK_SearchKeys(LayoutHandle *handle,ObjectNode *group) { ObjectNode *node; ULONG page; SCANPAGE(group,node,page) { if(node -> Type == GROUP_KIND) LTK_SearchKeys(handle,node); else { if(node -> Key) { WORD i; for(i = 0 ; i < 256 ; i++) { if(LTK_Keys[0][i] == node -> Key || LTK_Keys[1][i] == node -> Key) { handle -> Keys[LTK_Keys[0][i]] = TRUE; handle -> Keys[LTK_Keys[1][i]] = TRUE; break; } } if(LTK_Keys[1][node -> Key]) node -> Key = LTK_Keys[0][node -> Key]; } else { if((handle -> CursorKey == node) || (handle -> ReturnKey == node) || (handle -> EscKey == node)) node -> NoKey = TRUE; } } } } #endif /*****************************************************************************/ #ifdef DO_PICKSHORTCUTS STATIC VOID __regargs LTK_SelectKeys(LayoutHandle *handle,ObjectNode *group) { UBYTE bunch; ObjectNode *node; ULONG page; SCANPAGE(group,node,page) { bunch = 0; switch(node -> Type) { case GROUP_KIND: LTK_SelectKeys(handle,node); break; case TEXT_KIND: if(!node -> Special . Text . UsePicker) break; case FRACTION_KIND: case PASSWORD_KIND: case STRING_KIND: if(node -> Special . String . UsePicker) bunch = 255; case BUTTON_KIND: case CHECKBOX_KIND: case INTEGER_KIND: bunch++; case LISTVIEW_KIND: case MX_KIND: case CYCLE_KIND: case PALETTE_KIND: case SCROLLER_KIND: case SLIDER_KIND: bunch++; if(node -> Label && !node -> Key && !node -> NoKey) { WORD i,len,code,glyph; STRPTR label; label = node -> Label; len = strlen(label); for(i = 0 ; i < len ; i++) { glyph = ToLower(label[i]); code = -1; if(bunch == 1) // Support increment & decrement { if(LTK_Keys[0][glyph] && LTK_Keys[1][glyph]) code = LTK_Keys[0][glyph]; } else { if(bunch == 2) { if(LTK_Keys[0][glyph]) code = LTK_Keys[0][glyph]; else { if(LTK_Keys[1][glyph] && LTK_Keys[0][glyph]) { if(ToLower(LTK_Keys[1][glyph]) == glyph) code = LTK_Keys[0][glyph]; } } } } if(code != -1 && !handle -> Keys[code]) { STRPTR newLabel; if(newLabel = LTK_Alloc(handle,len + 2)) { node -> Label = newLabel; node -> Key = code; if(i) CopyMem(label,newLabel,i); newLabel[i] = '_'; CopyMem(label + i,&newLabel[i + 1],len - i); handle -> Keys[code] = handle -> Keys[LTK_Keys[1][code]] = TRUE; break; } } } } break; } } } #endif /*****************************************************************************/ STATIC ObjectNode * __regargs LTK_CreateObjectNode(LayoutHandle *handle,UBYTE type,ULONG id,STRPTR label) { ObjectNode *node; ULONG size,extra; switch(type) { #ifdef DO_GAUGE_KIND case GAUGE_KIND: extra = sizeof(GaugeExtra); break; #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: extra = sizeof(TapeDeckExtra); break; #endif /* DO_TAPEDECK_KIND */ case BUTTON_KIND: extra = sizeof(ButtonExtra); break; case XBAR_KIND: case YBAR_KIND: extra = sizeof(BarExtra); break; case BOX_KIND: extra = sizeof(BoxExtra); break; case FRAME_KIND: extra = sizeof(FrameExtra); break; case PICKER_KIND: extra = sizeof(PickerExtra); break; case INCREMENTER_KIND: extra = sizeof(IncrementerExtra); break; case LISTVIEW_KIND: extra = sizeof(ListExtra); break; case MX_KIND: extra = sizeof(RadioExtra); break; case TEXT_KIND: extra = sizeof(TextExtra); break; case NUMBER_KIND: extra = sizeof(NumberExtra); break; case CYCLE_KIND: extra = sizeof(CycleExtra); break; case PALETTE_KIND: extra = sizeof(PalExtra); break; case SLIDER_KIND: extra = sizeof(SliderExtra); break; case SCROLLER_KIND: extra = sizeof(ScrollerExtra); break; case INTEGER_KIND: extra = sizeof(IntegerExtra); break; case FRACTION_KIND: case PASSWORD_KIND: case STRING_KIND: extra = sizeof(StringExtra); break; case HORIZONTAL_KIND: case VERTICAL_KIND: extra = sizeof(GroupExtra); break; default: extra = 0; break; } size = offsetof(ObjectNode,Special) + extra; if(node = LTK_Alloc(handle,size)) { node -> Type = type; node -> Label = label; node -> ID = id; node -> PointBack = node; switch(type) { case LISTVIEW_KIND: node -> LabelPlace = PLACE_ABOVE; node -> Lines = 1; node -> Current = ~0; node -> Special . List . LinkID = -1; break; case PASSWORD_KIND: case STRING_KIND: node -> Special . String . LayoutHandle = handle; node -> Special . String . LinkID = -1; node -> Special . String . MaxChars = 256; node -> Special . String . MaxHistoryLines = 0; break; case INTEGER_KIND: node -> Special . Integer . LayoutHandle = handle; node -> Special . Integer . Min = -2147483647; node -> Special . Integer . Max = 2147483647; node -> Special . Integer . MaxChars = 11; node -> Special . Integer . MaxHistoryLines = 0; break; #ifdef DO_FRACTION_KIND case FRACTION_KIND: node -> Special . String . LayoutHandle = handle; node -> Special . String . LinkID = -1; node -> Special . String . Min = 0; node -> Special . String . Max = 2147483647; node -> Special . String . MaxChars = 12; node -> Special . String . MaxHistoryLines = 0; break; #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: node -> LabelPlace = PLACE_BELOW; break; #endif /* DO_TAPEDECK_KIND */ case MX_KIND: node -> LabelPlace = PLACE_RIGHT; node -> Special . Radio . TitlePlace = PLACETEXT_LEFT; break; case SCROLLER_KIND: node -> Special . Scroller . Visible = 2; break; case SLIDER_KIND: node -> Special . Slider . LevelPlace = PLACETEXT_LEFT; break; case FRAME_KIND: node -> Special . Frame . DrawBox = TRUE; break; case BOX_KIND: node -> Special . Box . DrawBox = TRUE; break; case HORIZONTAL_KIND: node -> Type = GROUP_KIND; node -> Special . Group . Horizontal = TRUE; break; case VERTICAL_KIND: node -> Type = GROUP_KIND; node -> Special . Group . Horizontal = FALSE; break; } } return(node); } /*****************************************************************************/ STATIC VOID __regargs LTK_DeleteObjectNode(LayoutHandle *handle,ObjectNode *node) { struct Image **ImagePtr = NULL; if(node -> Type == PICKER_KIND) { if(node -> Special . Picker . Image) ImagePtr = &node -> Special . Picker . Image; } else { if(node -> Type == INCREMENTER_KIND) ImagePtr = &node -> Special . Incrementer . Image; else { if(node -> Type == TAPEDECK_KIND) ImagePtr = &node -> Special . TapeDeck . ButtonImage; } } if(ImagePtr) { if(*ImagePtr) { DisposeObject(*ImagePtr); *ImagePtr = NULL; } } } /*****************************************************************************/ STATIC struct Gadget * __regargs LTK_CreatePicker(LayoutHandle *handle,ObjectNode *parentNode,struct Gadget *parentGadget,struct NewGadget *ng) { ObjectNode *node; struct Gadget *picker; if(node = LTK_CreateObjectNode(handle,PICKER_KIND,parentGadget -> GadgetID,NULL)) { ng -> ng_LeftEdge = ng -> ng_LeftEdge + ng -> ng_Width; ng -> ng_Width = (ng -> ng_Height * handle -> AspectY) / handle -> AspectX; ng -> ng_GadgetText = ""; ng -> ng_UserData = node; ng -> ng_Flags = NULL; node -> Special . Picker . Image = NewObject(LTK_ImageClass,NULL, IIA_ImageType, IMAGECLASS_PICKER, IA_Width, ng -> ng_Width, IA_Height, ng -> ng_Height, TAG_DONE); if(node -> Special . Picker . Image) { if(picker = CreateGadgetA(GENERIC_KIND,parentGadget,ng,NULL)) { picker -> GadgetType |= GTYP_BOOLGADGET; picker -> Flags |= GFLG_GADGIMAGE | GFLG_GADGHIMAGE; picker -> Activation |= GACT_RELVERIFY; picker -> GadgetRender = node -> Special . Picker . Image; picker -> SelectRender = node -> Special . Picker . Image; if(parentNode -> Disabled) picker -> Flags |= GFLG_DISABLED; node -> Host = picker; node -> Special . Picker . Parent = parentGadget; return(picker); } else LTK_DeleteObjectNode(handle,node); } } return(NULL); } /*****************************************************************************/ STATIC struct Gadget * __regargs LTK_CreateIncrementer(LayoutHandle *handle,ObjectNode *parentNode,struct Gadget *parentGadget,struct NewGadget *ng,BOOLEAN leftDirection,LONG incAmount) { ObjectNode *node; struct Gadget *incer; if(node = LTK_CreateObjectNode(handle,INCREMENTER_KIND,parentGadget -> GadgetID,NULL)) { ng -> ng_LeftEdge = ng -> ng_LeftEdge + ng -> ng_Width; ng -> ng_Width = (((ng -> ng_Height * handle -> AspectY) / handle -> AspectX) * 4) / 5, ng -> ng_GadgetText = ""; ng -> ng_UserData = node; ng -> ng_Flags = NULL; node -> Special . Incrementer . Amount = incAmount; if(leftDirection) { node -> Special . Incrementer . Image = NewObject(LTK_ImageClass,NULL, IIA_ImageType, IMAGECLASS_LEFTINCREMENTER, IA_Width, ng -> ng_Width, IA_Height, ng -> ng_Height, TAG_DONE); } else { node -> Special . Incrementer . Image = NewObject(LTK_ImageClass,NULL, IIA_ImageType, IMAGECLASS_RIGHTINCREMENTER, IA_Width, ng -> ng_Width, IA_Height, ng -> ng_Height, TAG_DONE); } if(node -> Special . Incrementer . Image) { if(incer = CreateGadgetA(GENERIC_KIND,handle -> Previous,ng,NULL)) { incer -> GadgetType |= GTYP_BOOLGADGET; incer -> Flags |= GFLG_GADGIMAGE | GFLG_GADGHIMAGE; incer -> Activation |= GACT_IMMEDIATE | GACT_RELVERIFY; incer -> GadgetRender = node -> Special . Incrementer . Image; incer -> SelectRender = node -> Special . Incrementer . Image; if(parentNode -> Disabled) incer -> Flags |= GFLG_DISABLED; node -> Host = incer; node -> Special . Incrementer . Parent = parentGadget; return(incer); } else LTK_DeleteObjectNode(handle,node); } } return(NULL); } /*****************************************************************************/ STATIC VOID __regargs LTK_LayoutGadgets(LayoutHandle *Handle,ObjectNode *Group) { if(!Handle -> Failed) { STATIC struct TagItem NoUnderscoreVanillaTags[] = { {TAG_DONE} }; STATIC struct TagItem VanillaTags[] = { {GT_Underscore, '_'}, {TAG_DONE} }; STATIC struct TagItem DisabledTags[] = { {GT_Underscore, '_' }, {GA_Disabled, TRUE}, {TAG_DONE} }; STATIC struct TagItem NoUnderscoreDisabledTags[] = { {GA_Disabled, TRUE}, {TAG_DONE} }; struct NewGadget NewGadget; struct Gadget *Gadget, *Extra; struct TagItem *Tags; ULONG page; ObjectNode *Node; if(!Handle -> List) { if(!(Handle -> Previous = CreateContext(&Handle -> List))) { Handle -> Failed = TRUE; return; } } NewGadget . ng_TextAttr = Handle -> TextAttr; NewGadget . ng_VisualInfo = Handle -> VisualInfo; SCANPAGE(Group,Node,page) { if(Node -> Type != FRAME_KIND && Node -> Type != BOX_KIND && Node -> Type != XBAR_KIND && Node -> Type != YBAR_KIND) { Extra = NULL; if(Node -> GroupIndent) { NewGadget . ng_LeftEdge = Node -> Left + 4; NewGadget . ng_TopEdge = Node -> Top + 2; NewGadget . ng_Width = Node -> Width - (4 + 4); NewGadget . ng_Height = Node -> Height - (2 + 2); } else { NewGadget . ng_LeftEdge = Node -> Left; NewGadget . ng_TopEdge = Node -> Top; NewGadget . ng_Width = Node -> Width; NewGadget . ng_Height = Node -> Height; } NewGadget . ng_GadgetText = Node -> Label ? Node -> Label : (STRPTR)""; NewGadget . ng_GadgetID = Node -> ID; NewGadget . ng_UserData = Node; if(Node -> NoKey) { if(Node -> Disabled) { if(!V39 && (Node -> Type == MX_KIND || Node -> Type == LISTVIEW_KIND)) Tags = NoUnderscoreVanillaTags; else Tags = NoUnderscoreDisabledTags; } else Tags = NoUnderscoreVanillaTags; } else { if(Node -> Disabled) { if(!V39 && (Node -> Type == MX_KIND || Node -> Type == LISTVIEW_KIND)) Tags = VanillaTags; else Tags = DisabledTags; } else Tags = VanillaTags; } switch(Node -> LabelPlace) { case PLACE_LEFT: NewGadget . ng_Flags = PLACETEXT_LEFT; break; case PLACE_RIGHT: NewGadget . ng_Flags = PLACETEXT_RIGHT; break; case PLACE_ABOVE: NewGadget . ng_Flags = PLACETEXT_ABOVE; break; case PLACE_BELOW: NewGadget . ng_Flags = PLACETEXT_BELOW; break; case PLACE_IN: NewGadget . ng_Flags = PLACETEXT_IN; break; default: NewGadget . ng_Flags = NULL; break; } if(Node -> HighLabel) NewGadget . ng_Flags |= NG_HIGHLABEL; switch(Node -> Type) { case BUTTON_KIND: Gadget = CreateGadgetA(BUTTON_KIND,Handle -> Previous,&NewGadget,Tags); break; case GROUP_KIND: LTK_LayoutGadgets(Handle,Node); continue; case CHECKBOX_KIND: Gadget = CreateGadget(CHECKBOX_KIND,Handle -> Previous,&NewGadget, GTCB_Checked, Node -> Current, GTCB_Scaled, TRUE, TAG_MORE,Tags); break; case LISTVIEW_KIND: if(!Node -> Special . List . ReadOnly && Node -> Special . List . LinkID != -1 && Node -> Special . List . LinkID != NIL_LINK) Gadget = Node -> Special . List . Link = LTK_FindGadget(Handle,Node -> Special . List . LinkID); else Gadget = NULL; Gadget = CreateGadget(LISTVIEW_KIND,Handle -> Previous,&NewGadget, GTLV_Selected, Node -> Current, GTLV_ReadOnly, Node -> Special . List . ReadOnly, GTLV_ScrollWidth, 2 + 2 * Handle -> GlyphWidth + 2, Node -> Current >= 0 ? GTLV_Top: TAG_IGNORE,Node -> Current, Node -> Current >= 0 ? GTLV_MakeVisible: TAG_IGNORE,Node -> Current, Node -> Special . List . Labels ? GTLV_Labels: TAG_IGNORE,Node -> Special . List . Labels, Node -> Special . List . LinkID != -1 ? GTLV_ShowSelected: TAG_IGNORE,Gadget, Node -> Special . List . CallBack ? GTLV_CallBack: TAG_IGNORE,Node -> Special . List . CallBack, Node -> Special . List . MaxPen ? GTLV_MaxPen: TAG_IGNORE,Node -> Special . List . MaxPen, TAG_MORE,Tags); break; case MX_KIND: NewGadget . ng_Height = Handle -> RPort . TxHeight; Gadget = CreateGadget(MX_KIND,Handle -> Previous,&NewGadget, GTMX_Labels, Node -> Special . Radio . Choices, GTMX_Active, Node -> Current, GTMX_Spacing, Handle -> InterHeight, GTMX_Scaled, TRUE, Node -> Label ? GTMX_TitlePlace : TAG_IGNORE, Node -> Special . Radio . TitlePlace, TAG_MORE,Tags); break; case TEXT_KIND: if(Node -> Special . Text . UsePicker) NewGadget . ng_Width -= (NewGadget . ng_Height * Handle -> AspectY) / Handle -> AspectX; if(Gadget = CreateGadget(TEXT_KIND,Handle -> Previous,&NewGadget, GTTX_Border, Node -> Special . Text . Border, GTTX_Justification, Node -> Special . Text . Justification, Node -> Special . Text . Text ? GTTX_Text : TAG_IGNORE,Node -> Special . Text . Text, TAG_MORE,Tags)) { if(Node -> Special . Text . UsePicker) { Extra = LTK_CreatePicker(Handle,Node,Gadget,&NewGadget); if(!Extra) Gadget = NULL; Node -> Special . Text . Picker = Extra; } } break; #ifdef DO_GAUGE_KIND case GAUGE_KIND: NewGadget . ng_Height -= Handle -> InterHeight + Handle -> RPort . TxHeight + 2; Gadget = CreateGadgetA(TEXT_KIND,Handle -> Previous,&NewGadget,NULL); break; #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: if(Node -> Special . TapeDeck . ButtonType >= TDBT_BACKWARD && Node -> Special . TapeDeck . ButtonType < TDBTLAST) { LONG ImageType; UWORD Activation, Flags; if(Node -> Special . TapeDeck . Toggle) Activation = GACT_TOGGLESELECT | GACT_IMMEDIATE; else Activation = GACT_RELVERIFY; if(Node -> Current) Flags = GFLG_GADGIMAGE | GFLG_GADGHIMAGE | GFLG_SELECTED; else Flags = GFLG_GADGIMAGE | GFLG_GADGHIMAGE; switch(Node -> Special . TapeDeck . ButtonType) { case TDBT_BACKWARD: ImageType = IMAGECLASS_BACKWARD; break; case TDBT_FORWARD: ImageType = IMAGECLASS_FORWARD; break; case TDBT_PREVIOUS: ImageType = IMAGECLASS_PREVIOUS; break; case TDBT_NEXT: ImageType = IMAGECLASS_NEXT; break; case TDBT_RECORD: ImageType = IMAGECLASS_RECORD; break; case TDBT_PLAY: ImageType = IMAGECLASS_PLAY; break; case TDBT_STOP: ImageType = IMAGECLASS_STOP; break; case TDBT_PAUSE: ImageType = IMAGECLASS_PAUSE; break; case TDBT_REWIND: ImageType = IMAGECLASS_REWIND; break; case TDBT_EJECT: ImageType = IMAGECLASS_EJECT; break; } if(Node -> Special . TapeDeck . ButtonImage = NewObject(LTK_ImageClass,NULL, IIA_ImageType, ImageType, IIA_GlyphWidth, Node -> Special . TapeDeck . ButtonWidth, IIA_GlyphHeight,Node -> Special . TapeDeck . ButtonHeight, IA_Width, NewGadget . ng_Width, IA_Height, NewGadget . ng_Height, TAG_DONE)) { NewGadget . ng_GadgetText = ""; NewGadget . ng_Flags = NULL; if(Gadget = CreateGadgetA(GENERIC_KIND,Handle -> Previous,&NewGadget,NULL)) { Gadget -> GadgetType |= GTYP_BOOLGADGET; Gadget -> Flags |= Flags; Gadget -> Activation |= Activation; Gadget -> GadgetRender = Node -> Special . TapeDeck . ButtonImage; Gadget -> SelectRender = Node -> Special . TapeDeck . ButtonImage; if(Node -> Disabled) Gadget -> Flags |= GFLG_DISABLED; } } } break; #endif /* DO_TAPEDECK_KIND */ case NUMBER_KIND: Gadget = CreateGadget(NUMBER_KIND,Handle -> Previous,&NewGadget, GTNM_Number, Node -> Special . Number . Number, GTNM_Border, Node -> Special . Number . Border, GTNM_Justification, Node -> Special . Number . Justification, GTNM_Border, Node -> Special . Number . Border, GTNM_Justification, Node -> Special . Number . Justification, TAG_MORE,Tags); break; case CYCLE_KIND: Gadget = CreateGadget(CYCLE_KIND,Handle -> Previous,&NewGadget, GTCY_Labels, Node -> Special . Cycle . Choices, GTCY_Active, Node -> Current, TAG_MORE,Tags); break; case PALETTE_KIND: Gadget = CreateGadget(PALETTE_KIND,Handle -> Previous,&NewGadget, GTPA_Depth, Node -> Special . Palette . Depth, GTPA_Color, Node -> Current, GTPA_ColorOffset, Node -> Min, GTPA_IndicatorWidth, MAX(10,Node -> Width / (Node -> Max - Node -> Min + 1)), GTPA_IndicatorHeight, Node -> Height, Node -> Special . Palette . ColourTable ? GTPA_ColorTable : TAG_IGNORE,Node -> Special . Palette . ColourTable, TAG_MORE,Tags); break; case SLIDER_KIND: Gadget = CreateGadget(SLIDER_KIND,Handle -> Previous,&NewGadget, GTSL_Min, Node -> Min, GTSL_Max, Node -> Max, GTSL_Level, Node -> Current, GTSL_MaxLevelLen, Node -> Special . Slider . MaxLevelLen, GTSL_LevelPlace, Node -> Special . Slider . LevelPlace, GTSL_LevelFormat, Node -> Special . Slider . LevelFormat ? Node -> Special . Slider . LevelFormat : (STRPTR)"%ld", GA_RelVerify, TRUE, V40 ? GTSL_MaxPixelLen : TAG_IGNORE, Node -> Special . Slider . LevelWidth, V40 ? GTSL_Justification : TAG_IGNORE, GTJ_RIGHT, Node -> Special . Slider . DispFunc ? GTSL_DispFunc : TAG_IGNORE,Node -> Special . Slider . DispFunc, TAG_MORE,Tags); break; case SCROLLER_KIND: Gadget = CreateGadget(SCROLLER_KIND,Handle -> Previous,&NewGadget, GA_RelVerify, Node -> Special . Scroller . RelVerify, GA_Immediate, Node -> Special . Scroller . Immediate, GTSC_Top, Node -> Current, GTSC_Total, Node -> Max, GTSC_Visible, Node -> Special . Scroller . Visible, PGA_Freedom, Node -> Special . Scroller . Vertical ? LORIENT_VERT : LORIENT_HORIZ, Node -> Special . Scroller . Arrows ? GTSC_Arrows : TAG_IGNORE,Node -> Special . Scroller . ArrowSize, TAG_MORE,Tags); break; case STRING_KIND: if(Node -> Special . String . LinkID != -1) { ObjectNode *ListView = LTK_FindNode(Handle -> TopGroup,Node -> Special . String . LinkID); if(ListView) { NewGadget . ng_LeftEdge = ListView -> Left; NewGadget . ng_TopEdge = ListView -> Top + ListView -> Height; NewGadget . ng_Width = ListView -> Width; } } if(Node -> Special . String . UsePicker) NewGadget . ng_Width -= (NewGadget . ng_Height * Handle -> AspectY) / Handle -> AspectX; if(Gadget = CreateGadget(STRING_KIND,Handle -> Previous,&NewGadget, GTST_String, Node -> Special . String . String, GTST_MaxChars, Node -> Special . String . MaxChars, GTST_EditHook, Node -> Special . String . EditHook ? Node -> Special . String . EditHook : Handle -> StandardEditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . String . Justification, TAG_MORE,Tags)) { if(!V39) Gadget -> Activation |= GACT_IMMEDIATE; if(Node -> Special . String . UsePicker) { Extra = LTK_CreatePicker(Handle,Node,Gadget,&NewGadget); if(!Extra) Gadget = NULL; Node -> Special . String . Picker = Extra; } } break; #ifdef DO_FRACTION_KIND case FRACTION_KIND: if(Node -> Special . String . LinkID != -1) { ObjectNode *ListView = LTK_FindNode(Handle -> TopGroup,Node -> Special . String . LinkID); if(ListView) { NewGadget . ng_LeftEdge = ListView -> Left; NewGadget . ng_TopEdge = ListView -> Top + ListView -> Height; NewGadget . ng_Width = ListView -> Width; } } /* ALWAYS */ { UBYTE LocalBuffer[20]; sprintf(LocalBuffer,"%ld%lc%ld",Node -> Current / FIXED_UNITY,LTK_Locale ? LTK_Locale -> loc_DecimalPoint[0] : ' . ',Node -> Current % FIXED_UNITY); if(Gadget = CreateGadget(STRING_KIND,Handle -> Previous,&NewGadget, GTST_String, LocalBuffer, GTST_MaxChars, Node -> Special . String . MaxChars > 12 ? 12 : Node -> Special . String . MaxChars, GTST_EditHook, &Handle -> FracEditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . String . Justification, TAG_MORE,Tags)) { if(!V39) Gadget -> Activation |= GACT_IMMEDIATE; } } break; #endif #ifdef DO_PASSWORD_KIND case PASSWORD_KIND: { WORD Len; if(Len = strlen(Node -> Special . String . Original)) memset(Node -> Special . String . Original,'·',Len); if(Gadget = CreateGadget(STRING_KIND,Handle -> Previous,&NewGadget, GTST_String, Node -> Special . String . Original, GTST_MaxChars, Node -> Special . String . MaxChars, GTST_EditHook, &Handle -> PasswordEditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . String . Justification, TAG_MORE,Tags)) { if(!V39) Gadget -> Activation |= GACT_IMMEDIATE; } if(Len) strcpy(Node -> Special . String . Original,Node -> Special . String . RealString); break; } #endif case INTEGER_KIND: if(Node -> Special . Integer . UseIncrementers) { NewGadget . ng_Width -= (((NewGadget . ng_Height * Handle -> AspectY) / Handle -> AspectX) * 4) / 5; NewGadget . ng_Width -= (((NewGadget . ng_Height * Handle -> AspectY) / Handle -> AspectX) * 4) / 5; if(Node -> Special . Integer . IncrementerHook) { LONG Value; Value = (LONG)CallHookPkt(Node -> Special . Integer . IncrementerHook,(APTR)Node -> Special . Integer . Number,(APTR)INCREMENTERMSG_INITIAL); if(Value < Node -> Special . Integer . Min) Value = Node -> Special . Integer . Min; else { if(Value > Node -> Special . Integer . Max) Value = Node -> Special . Integer . Max; } Node -> Special . Integer . Number = Value; } } #ifndef DO_HEXHOOK Gadget = CreateGadget(INTEGER_KIND,Handle -> Previous,&NewGadget, GTIN_Number, Node -> Special . Integer . Number, GTIN_MaxChars, Node -> Special . Integer . MaxChars, GTIN_EditHook, Node -> Special . Integer . EditHook ? Node -> Special . Integer . EditHook : Handle -> StandardEditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . Integer . Justification, TAG_MORE,Tags); #else if(Node -> Special . Integer . EditHook) { Gadget = CreateGadget(INTEGER_KIND,Handle -> Previous,&NewGadget, GTIN_Number, Node -> Special . Integer . Number, GTIN_MaxChars, Node -> Special . Integer . MaxChars, GTIN_EditHook, Node -> Special . Integer . EditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . Integer . Justification, TAG_MORE,Tags); } else { UBYTE LocalBuffer[20]; sprintf(LocalBuffer,"%ld",Node -> Special . Integer . Number); Gadget = CreateGadget(STRING_KIND,Handle -> Previous,&NewGadget, GTST_String, LocalBuffer, GTST_MaxChars, Node -> Special . Integer . MaxChars, GTST_EditHook, &Handle -> HexEditHook, GA_Immediate, TRUE, STRINGA_Justification, Node -> Special . Integer . Justification, TAG_MORE,Tags); } if(Gadget) { struct StringInfo *StringInfo = (struct StringInfo *)Gadget -> SpecialInfo; StringInfo -> LongInt = Node -> Special . Integer . Number; } #endif if(Gadget) { if(!V39) Gadget -> Activation |= GACT_IMMEDIATE; if(Node -> Special . Integer . UseIncrementers) { Handle -> Previous = Gadget; if(Node -> Special . Integer . LeftIncrementer = LTK_CreateIncrementer(Handle,Node,Gadget,&NewGadget,TRUE,-1)) { Handle -> Previous = Node -> Special . Integer . LeftIncrementer; if(Node -> Special . Integer . RightIncrementer = LTK_CreateIncrementer(Handle,Node,Gadget,&NewGadget,FALSE,1)) Extra = Node -> Special . Integer . RightIncrementer; else Gadget = NULL; } else Gadget = NULL; } } break; } if(Gadget) { Handle -> GadgetArray[Handle -> Index++] = Gadget; if(Extra) Handle -> Previous = Extra; else Handle -> Previous = Gadget; Node -> Host = Gadget; } else { Handle -> Failed = TRUE; return; } } } } } /*****************************************************************************/ STATIC BOOLEAN __regargs LTK_GlyphSetup(struct LayoutHandle *Handle,struct TextAttr *TextAttr) { struct TextFont *Font; if(TextAttr) { Handle -> TextAttr = TextAttr; if(!(Font = OpenFont(Handle -> TextAttr))) { struct Library *DiskfontBase; if(DiskfontBase = OpenLibrary("diskfont.library",0)) { Font = OpenDiskFont(Handle -> TextAttr); CloseLibrary(DiskfontBase); } } if(Font) { if(Handle -> CloseFont) CloseFont(Handle -> RPort . Font); else Handle -> CloseFont = TRUE; } } else { Handle -> TextAttr = Handle -> Screen -> Font; Font = Handle -> DrawInfo -> dri_Font; if(Handle -> CloseFont) { CloseFont(Handle -> RPort . Font); Handle -> CloseFont = FALSE; } } if(Font) { LONG Count = 0; LONG Total = 0; UBYTE Glyph; UWORD i; LTK_SetFont(Handle,Font); for(i = 32 ; i < 127 ; i++,Count++) { Glyph = i; Total += TextLength(&Handle -> RPort,&Glyph,1); } for(i = 160 ; i < 256 ; i++,Count++) { Glyph = i; Total += TextLength(&Handle -> RPort,&Glyph,1); } Handle -> GlyphWidth = Total / Count; if(Handle -> GlyphWidth <= 8) Handle -> InterWidth = 4; else Handle -> InterWidth = Handle -> GlyphWidth / 2; if(Handle -> RPort . TxHeight <= 8) Handle -> InterHeight = 2; else Handle -> InterHeight = Handle -> RPort . TxHeight / 4; return(TRUE); } else return(FALSE); } /*****************************************************************************/ #ifdef DO_CLONING STATIC VOID __regargs LTK_CloneScreen(struct LayoutHandle *Handle,LONG Width,LONG Height) { struct ColorSpec *ColourSpec; struct ColourRecord *ColourRecord; struct CloneExtra *Extra = Handle -> CloneExtra; LONG AllocationSize; UWORD i,j,*Pens = Handle -> CloneExtra -> ScreenPens; struct Screen *Screen; Height += Handle -> Screen -> BarHeight + 1; if(Width < Extra -> MinWidth) Width = Extra -> MinWidth; if(Height < Extra -> MinHeight) Height = Extra -> MinHeight; if(V39) { if(!(ColourRecord = (struct ColourRecord *)AsmAllocPooled(Handle -> Pool,AllocationSize = sizeof(struct ColourRecord) + sizeof(struct ColourTriplet) * Extra -> TotalPens,SysBase))) { Handle -> Failed = TRUE; return; } else { memset(ColourRecord,0,AllocationSize); ColourRecord -> NumColours = Extra -> TotalPens; ColourSpec = NULL; for(i = 0 ; i < Extra -> TotalPens ; i++) GetRGB32(Handle -> Screen -> ViewPort . ColorMap,Extra -> Pens[i],1,(ULONG *)&ColourRecord -> Triplets[i]); } } else { if(!(ColourSpec = (struct ColorSpec *)AsmAllocPooled(Handle -> Pool,AllocationSize = sizeof(struct ColorSpec) * (Extra -> TotalPens + 1),SysBase))) { Handle -> Failed = TRUE; return; } else { UWORD RGB; ColourRecord = NULL; for(i = 0 ; i < Extra -> TotalPens ; i++) { RGB = GetRGB4(Handle -> Screen -> ViewPort . ColorMap,Extra -> Pens[i]); ColourSpec[i] . ColorIndex = i; ColourSpec[i] . Red = (RGB >> 8) & 0xF; ColourSpec[i] . Green = (RGB >> 4) & 0xF; ColourSpec[i] . Blue = (RGB ) & 0xF; } ColourSpec[i] . ColorIndex = -1; } } if(Handle -> ExactClone) { for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++) Pens[i] = Extra -> Pens[i]; } else { for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++) { for(j = 0 ; j < Extra -> TotalPens ; j++) { if(Extra -> Pens[j] == Handle -> DrawInfo -> dri_Pens[i]) { Pens[i] = j; break; } } } } Pens[i] = (UWORD)~0; if(Screen = OpenScreenTags(NULL, SA_Width, Width, SA_Height, Height, SA_Overscan, OSCAN_TEXT, SA_BlockPen, Pens[SHADOWPEN], SA_DetailPen, Pens[BACKGROUNDPEN], SA_AutoScroll, TRUE, SA_DisplayID, GetVPModeID(&Handle -> Screen -> ViewPort), SA_Behind, TRUE, SA_BackFill, &Handle -> BackfillHook, SA_Depth, Extra -> Depth, SA_Colors, ColourSpec, SA_Colors32, ColourRecord, SA_Pens, Pens, SA_Font, Handle -> TextAttr, SA_Title, Handle -> Screen -> DefaultTitle, TAG_DONE)) { struct DrawInfo *DrawInfo; if(DrawInfo = GetScreenDrawInfo(Screen)) { APTR VisualInfo; if(VisualInfo = GetVisualInfoA(Screen,NULL)) { UnlockPubScreen(NULL,Handle -> PubScreen); FreeScreenDrawInfo(Handle -> Screen,Handle -> DrawInfo); FreeVisualInfo(Handle -> VisualInfo); Handle -> PubScreen = NULL; Handle -> Screen = Screen; Handle -> DrawInfo = DrawInfo; Handle -> VisualInfo = VisualInfo; Handle -> TextPen = Handle -> DrawInfo -> dri_Pens[TEXTPEN]; Handle -> BackgroundPen = Handle -> DrawInfo -> dri_Pens[BACKGROUNDPEN]; Handle -> ShinePen = Handle -> DrawInfo -> dri_Pens[SHINEPEN]; Handle -> ShadowPen = Handle -> DrawInfo -> dri_Pens[SHADOWPEN]; Handle -> AspectX = Handle -> DrawInfo -> dri_Resolution . X; Handle -> AspectY = Handle -> DrawInfo -> dri_Resolution . Y; Handle -> MaxPen = Extra -> TotalPens - 1; Extra -> Screen = Screen; if(ColourRecord) AsmFreePooled(Handle -> Pool,ColourRecord,AllocationSize,SysBase); if(ColourSpec) AsmFreePooled(Handle -> Pool,ColourSpec,AllocationSize,SysBase); return; } FreeScreenDrawInfo(Screen,DrawInfo); } CloseScreen(Screen); } if(ColourRecord) AsmFreePooled(Handle -> Pool,ColourRecord,AllocationSize,SysBase); if(ColourSpec) AsmFreePooled(Handle -> Pool,ColourSpec,AllocationSize,SysBase); Handle -> Failed = TRUE; } STATIC BOOLEAN __regargs LTK_PrepareCloning(struct LayoutHandle *Handle) { if(Handle -> CloneExtra) return(TRUE); else { struct DimensionInfo DimensionInfo; if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,GetVPModeID(&Handle -> Screen -> ViewPort))) { if(Handle -> CloneExtra = (struct CloneExtra *)AsmAllocPooled(Handle -> Pool,sizeof(struct CloneExtra) + (sizeof(LONG) + sizeof(UWORD)) * Handle -> DrawInfo -> dri_NumPens + sizeof(UWORD),SysBase)) { UWORD i,j,TotalPens = 0; LONG *Pens; BOOLEAN NotFound; Handle -> CloneExtra -> Pens = (LONG *)(Handle -> CloneExtra + 1); Handle -> CloneExtra -> ScreenPens = (UWORD *)(&Handle -> CloneExtra -> Pens[Handle -> DrawInfo -> dri_NumPens]); Handle -> CloneExtra -> MinWidth = DimensionInfo . MinRasterWidth; Handle -> CloneExtra -> MinHeight = DimensionInfo . MinRasterHeight; Handle -> CloneExtra -> MaxWidth = DimensionInfo . MaxRasterWidth; Handle -> CloneExtra -> MaxHeight = DimensionInfo . MaxRasterHeight; Handle -> CloneExtra -> Bounds . Left = 0; Handle -> CloneExtra -> Bounds . Top = 0; Handle -> CloneExtra -> Bounds . Width = DimensionInfo . MaxRasterWidth; Handle -> CloneExtra -> Bounds . Height = DimensionInfo . MaxRasterHeight; Pens = Handle -> CloneExtra -> Pens; if(Handle -> ExactClone) { for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++) Pens[i] = Handle -> DrawInfo -> dri_Pens[i]; TotalPens = Handle -> DrawInfo -> dri_NumPens; Handle -> CloneExtra -> Depth = Handle -> DrawInfo -> dri_Depth; } else { for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++) { for(j = 0,NotFound = TRUE ; NotFound && j < TotalPens ; j++) { if(Pens[j] == Handle -> DrawInfo -> dri_Pens[i]) NotFound = FALSE; } if(NotFound) Pens[TotalPens++] = Handle -> DrawInfo -> dri_Pens[i]; } for(i = 0 ; i < DimensionInfo . MaxDepth ; i++) { if(TotalPens <= (1L << i)) { Handle -> CloneExtra -> Depth = i; break; } } } if((Handle -> CloneExtra -> TotalPens = TotalPens) && Handle -> CloneExtra -> Depth) { if(LTK_GlyphSetup(Handle,Handle -> InitialTextAttr)) { Handle -> Failed = Handle -> Rescaled = FALSE; LTK_ResetGroups(Handle -> TopGroup); if(!V39 && (Handle -> RPort . TxFlags & FPF_PROPORTIONAL)) { LTK_Rescale(Handle,FALSE,FALSE); Handle -> Rescaled = FALSE; } return(TRUE); } } else { AsmFreePooled(Handle -> Pool,Handle -> CloneExtra,sizeof(struct CloneExtra) + sizeof(LONG) * Handle -> DrawInfo -> dri_NumPens,SysBase); Handle -> CloneExtra = NULL; } } } } return(FALSE); } #endif /*****************************************************************************/ STATIC VOID __regargs LTK_CreateGadgets(LayoutHandle *Handle,struct IBox *Bounds,LONG Left,LONG Top,LONG PlusWidth,LONG PlusHeight) { if(!Handle -> Failed) { BOOLEAN Fits; BOOLEAN Cloned = FALSE; if(!V39 && (Handle -> RPort . TxFlags & FPF_PROPORTIONAL)) { LTK_Rescale(Handle,FALSE,FALSE); Handle -> Rescaled = FALSE; } do { LTK_LayoutGroup(Handle,Handle -> TopGroup); LTK_PlaceGroups(Handle,Handle -> TopGroup,Left,Top); Fits = TRUE; if(Handle -> TopGroup -> Width + PlusWidth > Bounds -> Width) { if(Handle -> TopGroup -> Width + PlusWidth > Handle -> Screen -> Width) { Fits = FALSE; if(Handle -> TopGroup -> Height + PlusHeight > Bounds -> Height) { if(!LTK_Rescale(Handle,TRUE,TRUE)) Handle -> Failed = TRUE; } else { if(!LTK_Rescale(Handle,TRUE,FALSE)) Handle -> Failed = TRUE; } } } else { if(Handle -> TopGroup -> Height + PlusHeight > Bounds -> Height) { if(Handle -> TopGroup -> Height + PlusHeight > Handle -> Screen -> Height) { Fits = FALSE; if(!LTK_Rescale(Handle,FALSE,TRUE)) Handle -> Failed = TRUE; } } } #ifdef DO_CLONING if(Handle -> Failed && !Cloned && Handle -> CloningPermitted) { if(LTK_PrepareCloning(Handle)) Bounds = &Handle -> CloneExtra -> Bounds; Cloned = TRUE; } #endif if(Fits && !Handle -> Rescaled && !Cloned && !Handle -> Failed && Handle -> GrowView) { LONG Width = Handle -> TopGroup -> Width + PlusWidth, Height = Handle -> TopGroup -> Height + PlusHeight; if(Bounds -> Width > Width || Bounds -> Height > Height) { ObjectNode *View = Handle -> GrowView; LONG PlusChars, PlusLines; if(View -> Special . List . MaxGrowX) { PlusChars = (Bounds -> Width - Width) / Handle -> GlyphWidth; if(PlusChars > 0 && View -> Chars + PlusChars > View -> Special . List . MaxGrowX) PlusChars = View -> Special . List . MaxGrowX - View -> Chars; if(PlusChars < 0) PlusChars = 0; } else PlusChars = 0; if(View -> Special . List . MaxGrowY) { PlusLines = (Bounds -> Height - Height) / Handle -> RPort . TxHeight; if(PlusLines > 0 && View -> Lines + PlusLines > View -> Special . List . MaxGrowY) PlusLines = View -> Special . List . MaxGrowY - View -> Lines; if(PlusLines < 0) PlusLines = 0; } else PlusLines = 0; if(PlusChars || PlusLines) { View -> Chars += PlusChars; View -> Lines += PlusLines; LTK_ResetGroups(Handle -> TopGroup); if(!V39 && (Handle -> RPort . TxFlags & FPF_PROPORTIONAL)) { LTK_Rescale(Handle,FALSE,FALSE); Handle -> Rescaled = FALSE; } Fits = FALSE; } } Handle -> GrowView = NULL; } } while(!Fits && !Handle -> Failed); #ifdef DO_CLONING if(!Handle -> Failed && Cloned) LTK_CloneScreen(Handle,Handle -> TopGroup -> Width + PlusWidth,Handle -> TopGroup -> Height + PlusHeight); #endif if(!Handle -> Failed) { if(Handle -> GadgetArray = LTK_Alloc(Handle,sizeof(struct Gadget *) * Handle -> Count)) { #ifdef DO_PICKSHORTCUTS LTK_SearchKeys(Handle,Handle -> TopGroup); LTK_SelectKeys(Handle,Handle -> TopGroup); #endif LTK_LayoutGadgets(Handle,Handle -> TopGroup); if(Handle -> Failed) { FreeGadgets(Handle -> List); Handle -> List = NULL; } } } } } /*****************************************************************************/ STATIC VOID __regargs LTK_PrintLabel(LayoutHandle *handle,ObjectNode *node,UWORD left,UWORD top) { STRPTR label; LONG len; LTK_SetAPen(&handle -> RPort,handle -> TextPen); Move(&handle -> RPort,left - (node -> LabelWidth + INTERWIDTH),top + handle -> RPort . TxBaseline + 1); label = node -> Label; len = 0; while(label[len] && (label[len] != '_')) len++; LockLayerRom(handle -> RPort . Layer); if(len) Text(&handle -> RPort,label,len); if(label[len] == '_' && label[len + 1]) { SetSoftStyle(&handle -> RPort,FSF_UNDERLINED,AskSoftStyle(&handle -> RPort)); Text(&handle -> RPort,label + len + 1,1); SetSoftStyle(&handle -> RPort,FS_NORMAL,AskSoftStyle(&handle -> RPort)); label += len + 2; if(len = strlen(label)) Text(&handle -> RPort,label,len); } UnlockLayerRom(handle -> RPort . Layer); } /*****************************************************************************/ STATIC VOID __regargs LTK_DrawGroup(LayoutHandle *Handle,ObjectNode *Group) { ObjectNode *Node; LONG i; ULONG page; if(Group -> Label) LTK_DrawLabel(Handle,Group); SCANPAGE(Group,Node,page) { switch(Node -> Type) { case BUTTON_KIND: if(Handle -> ReturnKey == Node) LTK_DrawBevelBox(Handle,Node); break; #ifdef DO_GAUGE_KIND case GAUGE_KIND: { LONG Percent = Node -> Current; Node -> Current = 0; LTK_DrawGauge(Handle,Node,Percent,TRUE); break; } #endif case GROUP_KIND: if(Node -> Label) LTK_DrawLabel(Handle,Node); LTK_DrawGroup(Handle,Node); break; case XBAR_KIND: { WORD Top = Node -> Top + ((Node -> Height + 1) / 2) - 1; LockLayerRom(Handle -> RPort . Layer); if(Node -> Special . Bar . FullSize) { LTK_SetAPen(&Handle -> RPort,Handle -> ShadowPen); Move(&Handle -> RPort,Handle -> Window -> BorderLeft,Top); Draw(&Handle -> RPort,Handle -> Window -> Width - (Handle -> Window -> BorderRight + 1),Top); LTK_SetAPen(&Handle -> RPort,Handle -> ShinePen); Move(&Handle -> RPort,Handle -> Window -> BorderLeft,Top + 1); Draw(&Handle -> RPort,Handle -> Window -> Width - (Handle -> Window -> BorderRight + 1),Top + 1); } else { if(Node -> Special . Bar . Parent -> Label) { LTK_SetAPen(&Handle -> RPort,Handle -> ShadowPen); Move(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + 2 * Handle -> GlyphWidth,Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + 2 * Handle -> GlyphWidth,Top); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - (2 * Handle -> GlyphWidth + 1) - 1,Top); LTK_SetAPen(&Handle -> RPort,Handle -> ShinePen); Move(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + 2 * Handle -> GlyphWidth + 1,Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - (2 * Handle -> GlyphWidth + 1),Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - (2 * Handle -> GlyphWidth + 1),Top); } else { LTK_SetAPen(&Handle -> RPort,Handle -> ShadowPen); Move(&Handle -> RPort,Node -> Special . Bar . Parent -> Left,Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left,Top); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - 1,Top); LTK_SetAPen(&Handle -> RPort,Handle -> ShinePen); Move(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + 1,Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - 1,Top + 1); Draw(&Handle -> RPort,Node -> Special . Bar . Parent -> Left + Node -> Special . Bar . Parent -> Width - 1,Top); } } UnlockLayerRom(Handle -> RPort . Layer); break; } case YBAR_KIND: { WORD Left = Node -> Left + ((Node -> Width + 1) / 2) - 1; LockLayerRom(Handle -> RPort . Layer); if(Node -> Special . Bar . Parent -> Label) { LTK_SetAPen(&Handle -> RPort,Handle -> ShadowPen); Move(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top + Handle -> RPort . TxHeight + Handle -> InterHeight); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top + Handle -> RPort . TxHeight + Handle -> InterHeight); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - (Handle -> RPort . TxHeight + Handle -> InterHeight + 1) - 1); LTK_SetAPen(&Handle -> RPort,Handle -> ShinePen); Move(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top + Handle -> RPort . TxHeight + Handle -> InterHeight + 1); Draw(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - (Handle -> RPort . TxHeight + Handle -> InterHeight + 1)); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - (Handle -> RPort . TxHeight + Handle -> InterHeight + 1)); } else { LTK_SetAPen(&Handle -> RPort,Handle -> ShadowPen); Move(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - 1 - 1); LTK_SetAPen(&Handle -> RPort,Handle -> ShinePen); Move(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top + 1); Draw(&Handle -> RPort,Left + 1,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - 1); Draw(&Handle -> RPort,Left,Node -> Special . Bar . Parent -> Top + Node -> Special . Bar . Parent -> Height - 1); } UnlockLayerRom(Handle -> RPort . Layer); break; } case FRAME_KIND: if(Node -> Special . Frame . DrawBox) LTK_DrawBevelBox(Handle,Node); // FALL THROUGH TO... case TAPEDECK_KIND: if(Node -> Label) { LTK_SetPens(&Handle -> RPort,Handle -> TextPen,Handle -> BackgroundPen,JAM2); switch(Node -> LabelPlace) { case PLACE_LEFT: LTK_PlaceText(Handle,Node -> Label,strlen(Node -> Label),Node -> Left - (Node -> LabelWidth + INTERWIDTH),Node -> Top + (Node -> Height - Handle -> RPort . TxHeight) / 2 + Handle -> RPort . TxBaseline); break; case PLACE_RIGHT: LTK_PlaceText(Handle,Node -> Label,strlen(Node -> Label),Node -> Left + Node -> Width + INTERWIDTH,Node -> Top + (Node -> Height - Handle -> RPort . TxHeight) / 2 + Handle -> RPort . TxBaseline); break; case PLACE_ABOVE: LTK_PlaceText(Handle,Node -> Label,strlen(Node -> Label),Node -> Left + (Node -> Width - Node -> LabelWidth) / 2,Node -> Top - (Handle -> RPort . TxHeight + INTERHEIGHT) + Handle -> RPort . TxBaseline); break; case PLACE_BELOW: LTK_PlaceText(Handle,Node -> Label,strlen(Node -> Label),Node -> Left + (Node -> Width - Node -> LabelWidth) / 2,Node -> Top + Node -> Height + INTERHEIGHT + Handle -> RPort . TxBaseline); break; } } break; case MX_KIND: if(Node -> Label && !V39) LTK_PrintLabel(Handle,Node,Node -> Left,Node -> Top + (Node -> Height - Handle -> RPort . TxHeight) / 2); break; case LISTVIEW_KIND: if(Node -> Special . List . ExtraLabels) { LockLayerRom(Handle -> RPort . Layer); LTK_SetPens(&Handle -> RPort,Handle -> TextPen,Handle -> BackgroundPen,JAM2); for(i = 0 ; Node -> Special . List . ExtraLabels[i] ; i++) { LONG Len = strlen(Node -> Special . List . ExtraLabels[i]); LTK_PlaceText(Handle,Node -> Special . List . ExtraLabels[i],Len,Node -> Left - (TextLength(&Handle -> RPort,Node -> Special . List . ExtraLabels[i],Len) + INTERWIDTH),Node -> Top + 2 + i * Handle -> RPort . TxHeight + Handle -> RPort . TxBaseline); } UnlockLayerRom(Handle -> RPort . Layer); } break; case BOX_KIND: if(Node -> Special . Box . DrawBox) LTK_DrawBevelBox(Handle,Node); LockLayerRom(Handle -> RPort . Layer); for(i = 0 ; i < Node -> Lines ; i++) { if(Node -> Special . Box . Labels && Node -> Special . Box . Labels[i]) { LONG Len = strlen(Node -> Special . Box . Labels[i]); LTK_SetPens(&Handle -> RPort,Handle -> TextPen,Handle -> BackgroundPen,JAM2); LTK_PlaceText(Handle,Node -> Special . Box . Labels[i],Len,Node -> Left - (TextLength(&Handle -> RPort,Node -> Special . Box . Labels[i],Len) + INTERWIDTH),Node -> Top + 2 + i * Handle -> RPort . TxHeight + Handle -> RPort . TxBaseline); } LTK_PrintBoxLine(Handle,Node,i); } UnlockLayerRom(Handle -> RPort . Layer); break; } } } /*****************************************************************************/ STATIC LONG __stdargs DefaultDispFunc(struct Gadget *gad,WORD value) { return(value); } VOID LIBENT LT_LevelWidth(REG(a0) LayoutHandle *handle,REG(a1) STRPTR levelFormat,REG(a2) DISPFUNC dispFunc,REG(d0) LONG min,REG(d1) LONG max,REG(a3) LONG *maxWidth,REG(a5) LONG *maxLen,REG(d2) BOOL fullCheck) { UBYTE buffer[80]; LONG localMaxWidth; LONG localMaxLen; LONG len; localMaxWidth = 0; localMaxLen = 0; if(handle) { if(!dispFunc) dispFunc = DefaultDispFunc; if(!levelFormat) levelFormat = "%ld"; if(fullCheck) { LONG i; for(i = min ; i <= max ; i++) { sprintf(buffer,levelFormat,(*dispFunc)(NULL,i)); len = strlen(buffer); if(len > localMaxLen) localMaxLen = len; len = TextLength(&handle -> RPort,buffer,len); if(len > localMaxWidth) localMaxWidth = len; } } else { sprintf(buffer,levelFormat,(*dispFunc)(NULL,min)); len = strlen(buffer); if(len > localMaxLen) localMaxLen = len; len = TextLength(&handle -> RPort,buffer,len); if(len > localMaxWidth) localMaxWidth = len; sprintf(buffer,levelFormat,(*dispFunc)(NULL,max)); len = strlen(buffer); if(len > localMaxLen) localMaxLen = len; len = TextLength(&handle -> RPort,buffer,len); if(len > localMaxWidth) localMaxWidth = len; } } if(maxLen) *maxLen = localMaxLen; if(maxWidth) *maxWidth = localMaxWidth + handle -> GlyphWidth; } /*****************************************************************************/ VOID LIBENT LT_DeleteHandle(REG(a0) LayoutHandle *Handle) { if(Handle) { UnlockPubScreen(NULL,Handle -> PubScreen); #ifdef DO_CLONING if(Handle -> CloneExtra) { if(Handle -> CloneExtra -> Screen) ScreenToBack(Handle -> CloneExtra -> Screen); } #endif if(Handle -> List) { struct Gadget *Gadget; ObjectNode *Node; if(Handle -> Window) RemoveGList(Handle -> Window,Handle -> List,(UWORD)-1); Gadget = Handle -> List; while(Gadget) { if(GETOBJECT(Gadget,Node)) LTK_DeleteObjectNode(Handle,Node); Gadget = Gadget -> NextGadget; } FreeGadgets(Handle -> List); } if(Handle -> Parent) LT_UnlockWindow(Handle -> Parent); if(Handle -> Window) { LT_DeleteWindowLock(Handle -> Window); if(Handle -> MsgPort && Handle -> Window -> UserPort) { struct IntuiMessage *intuiMsg; struct Node *next; Forbid(); intuiMsg = (struct IntuiMessage *)Handle -> Window -> UserPort -> mp_MsgList . lh_Head; while(next = intuiMsg -> ExecMessage . mn_Node . ln_Succ) { if(intuiMsg -> IDCMPWindow == Handle -> Window) { Remove(intuiMsg); ReplyMsg(intuiMsg); } intuiMsg = (struct IntuiMessage *)next; } Handle -> Window -> UserPort = NULL; ModifyIDCMP(Handle -> Window,NULL); Permit(); } ClearMenuStrip(Handle -> Window); CloseWindow(Handle -> Window); } DisposeObject(Handle -> AmigaGlyph); DisposeObject(Handle -> CheckGlyph); FreeScreenDrawInfo(Handle -> Screen,Handle -> DrawInfo); FreeVisualInfo(Handle -> VisualInfo); if(Handle -> RPort . Font && Handle -> CloseFont) CloseFont(Handle -> RPort . Font); #ifdef DO_CLONING if(Handle -> CloneExtra) { if(Handle -> CloneExtra -> Screen) CloseScreen(Handle -> CloneExtra -> Screen); } #endif if(Handle -> Pool) AsmDeletePool(Handle -> Pool,SysBase); if(Handle -> TimeRequest . tr_node . io_Device) CloseDevice(&Handle -> TimeRequest); FreeMem(Handle,sizeof(LayoutHandle)); } } /*****************************************************************************/ LayoutHandle * LIBENT LT_CreateHandle(REG(a0) struct Screen *Screen,REG(a1) struct TextAttr *Font) { return(LT_CreateHandleTags(Screen, LH_Font, Font, TAG_DONE)); } LayoutHandle * __stdargs LT_CreateHandleTags(struct Screen *Screen,...) { LayoutHandle *Handle; va_list VarArgs; va_start(VarArgs,Screen); Handle = LT_CreateHandleTagList(Screen,(struct TagItem *)VarArgs); va_end(VarArgs); return(Handle); } LayoutHandle * LIBENT LT_CreateHandleTagList(REG(a0) struct Screen *Screen,REG(a1) struct TagItem *TagList) { LayoutHandle *Handle; struct Screen *PubScreen; struct TextAttr *textAttr; #ifdef DO_PICKSHORTCUTS ObtainSemaphore(<K_KeySemaphore); if(!LTK_KeysInitialized) { UBYTE mapBuffer[2 * 3]; UBYTE remapBuffer[10]; LONG i; struct InputEvent event; for(i = 0 ; i < 256; i++) { if((i > ' ' && i < 127) || i > 160) { remapBuffer[0] = i; remapBuffer[1] = 0; if(MapANSI(remapBuffer,1,mapBuffer,3,NULL) == 1) { if(!(mapBuffer[1] & ~QUALIFIER_SHIFT)) { event . ie_NextEvent = NULL; event . ie_Class = IECLASS_RAWKEY; event . ie_SubClass = 0; event . ie_Code = mapBuffer[0]; event . ie_Qualifier = mapBuffer[1] & ~QUALIFIER_SHIFT; event . ie_position . ie_addr = NULL; if(MapRawKey(&event,remapBuffer,10,NULL) == 1) LTK_Keys[0][i] = remapBuffer[0]; event . ie_NextEvent = NULL; event . ie_Class = IECLASS_RAWKEY; event . ie_SubClass = 0; event . ie_Code = mapBuffer[0]; event . ie_Qualifier = mapBuffer[1] | QUALIFIER_SHIFT; event . ie_position . ie_addr = NULL; if(MapRawKey(&event,remapBuffer,10,NULL) == 1) LTK_Keys[1][i] = remapBuffer[0]; } } } } LTK_KeysInitialized = TRUE; } ReleaseSemaphore(<K_KeySemaphore); #endif /* DO_PICKSHORTCUTS */ textAttr = (struct TextAttr *)GetTagData(LH_Font,NULL,TagList); if(!Screen) { if(!(PubScreen = LockPubScreen(NULL))) return(NULL); else Screen = PubScreen; } else PubScreen = NULL; if(Handle = AllocMem(sizeof(LayoutHandle),MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR)) { Handle -> Screen = Screen; Handle -> PubScreen = PubScreen; Handle -> AutoActivate = GetTagData(LH_AutoActivate,FALSE,TagList); Handle -> LocaleHook = (struct Hook *)GetTagData(LH_LocaleHook,NULL,TagList); Handle -> Parent = (struct Window *)GetTagData(LH_Parent,NULL,TagList); Handle -> BlockParent = GetTagData(LH_BlockParent,FALSE,TagList); #ifdef DO_CLONING Handle -> CloningPermitted = GetTagData(LH_CloningPermitted,TRUE,TagList); Handle -> ExactClone = GetTagData(LH_ExactClone,FALSE,TagList); #endif #ifdef DO_FRACTION_KIND Handle -> FracEditHook . h_Entry = (HOOKFUNC)LTK_FracEditRoutine; Handle -> FracEditHook . h_Data = Handle; #endif #ifdef DO_PASSWORD_KIND Handle -> PasswordEditHook . h_Entry = (HOOKFUNC)LTK_PasswordEditRoutine; Handle -> PasswordEditHook . h_Data = Handle; #endif Handle -> DefaultEditHook . h_Entry = (HOOKFUNC)LTK_DefaultEditRoutine; Handle -> DefaultEditHook . h_Data = Handle; Handle -> BackfillHook . h_Entry = (HOOKFUNC)LTK_BackfillRoutine; Handle -> BackfillHook . h_Data = Handle; Handle -> StandardEditHook = (struct Hook *)GetTagData(LH_EditHook,(ULONG)&Handle -> DefaultEditHook,TagList); #ifdef DO_HEXHOOK Handle -> HexEditHook . h_Entry = (HOOKFUNC)LTK_HexEditRoutine; Handle -> HexEditHook . h_Data = Handle; #endif if(Handle -> Pool = AsmCreatePool(MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR,1024,1024,SysBase)) { if(Handle -> DrawInfo = GetScreenDrawInfo(Screen)) { LONG i; Handle -> TextPen = Handle -> DrawInfo -> dri_Pens[TEXTPEN]; Handle -> BackgroundPen = Handle -> DrawInfo -> dri_Pens[BACKGROUNDPEN]; Handle -> ShinePen = Handle -> DrawInfo -> dri_Pens[SHINEPEN]; Handle -> ShadowPen = Handle -> DrawInfo -> dri_Pens[SHADOWPEN]; Handle -> AspectX = Handle -> DrawInfo -> dri_Resolution . X; Handle -> AspectY = Handle -> DrawInfo -> dri_Resolution . Y; if(V39 && FindTagItem(LH_MenuGlyphs,TagList)) { LONG Size,FontHeight = Handle -> DrawInfo -> dri_Font -> tf_Baseline + 2; if(Screen -> Flags & SCREENHIRES) Size = SYSISIZE_MEDRES; else Size = SYSISIZE_LOWRES; if(Handle -> AmigaGlyph = NewObject(NULL,SYSICLASS, SYSIA_DrawInfo, Handle -> DrawInfo, SYSIA_Size, Size, SYSIA_Which, AMIGAKEY, IA_Left, 0, LA_Top, 0, IA_Width, (FontHeight * 3 * Handle -> AspectY) / (2 * Handle -> AspectX), IA_Height, FontHeight, TAG_DONE)) { if(!(Handle -> CheckGlyph = NewObject(NULL,SYSICLASS, SYSIA_DrawInfo, Handle -> DrawInfo, SYSIA_Size, Size, SYSIA_Which, MENUCHECK, IA_Left, 0, LA_Top, 0, IA_Width, (FontHeight * Handle -> AspectY) / Handle -> AspectX, IA_Height, FontHeight, TAG_DONE))) { DisposeObject(Handle -> AmigaGlyph); Handle -> AmigaGlyph = NULL; } } } for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++) { if(Handle -> DrawInfo -> dri_Pens[i] > Handle -> MaxPen) Handle -> MaxPen = Handle -> DrawInfo -> dri_Pens[i]; } if(Handle -> VisualInfo = GetVisualInfoA(Screen,NULL)) { if(textAttr) Handle -> InitialTextAttr = textAttr; InitRastPort(&Handle -> RPort); if(LTK_GlyphSetup(Handle,textAttr)) { #ifdef DO_PICKSHORTCUTS memset(Handle -> Keys,TRUE,256); for(i = 0 ; i < 256 ; i++) { if(i != 32 && i != 160) { if(LTK_Keys[0][i]) Handle -> Keys[LTK_Keys[0][i]] = FALSE; if(LTK_Keys[1][i]) Handle -> Keys[LTK_Keys[1][i]] = FALSE; } } #endif Handle -> TimePort . mp_Flags = PA_SIGNAL; Handle -> TimePort . mp_SigBit = SIGB_SINGLE; Handle -> TimePort . mp_SigTask = SysBase -> ThisTask; NewList((struct MinList *)&Handle -> TimePort . mp_MsgList); Handle -> TimeRequest . tr_node . io_Message . mn_ReplyPort = &Handle -> TimePort; Handle -> TimeRequest . tr_node . io_Message . mn_Length = sizeof(struct timerequest); OpenDevice(TIMERNAME,UNIT_VBLANK,&Handle -> TimeRequest,NULL); return(Handle); } } } } LT_DeleteHandle(Handle); } else UnlockPubScreen(NULL,PubScreen); return(NULL); } /*****************************************************************************/ STATIC VOID __regargs LTK_AddGadgets(LayoutHandle *handle) { if(handle) { AddGList(handle -> Window,handle -> List,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(handle -> List,handle -> Window,NULL,(UWORD)-1); GT_RefreshWindow(handle -> Window,NULL); LTK_DrawGroup(handle,handle -> TopGroup); } } /*****************************************************************************/ BOOL LIBENT LT_Rebuild(REG(a0) LayoutHandle *handle,REG(a1) struct IBox *bounds,REG(a2) LONG extraWidth,REG(d0) LONG extraHeight,REG(d1) BOOL clear) { if(handle) { struct Gadget *gadget; ObjectNode *node; LONG left,top; struct IBox newBounds; LONG i; RemoveGList(handle -> Window,handle -> List,(UWORD)-1); gadget = handle -> List; while(gadget) { if(GETOBJECT(gadget,node)) { node -> Host = NULL; switch(node -> Type) { case PICKER_KIND: if(node -> Special . Picker . Image) { DisposeObject(node -> Special . Picker . Image); node -> Special . Picker . Image = NULL; } break; case TAPEDECK_KIND: if(node -> Special . TapeDeck . ButtonImage) { DisposeObject(node -> Special . TapeDeck . ButtonImage); node -> Special . TapeDeck . ButtonImage = NULL; } break; case INCREMENTER_KIND: if(node -> Special . Incrementer . Image) { DisposeObject(node -> Special . Incrementer . Image); node -> Special . Incrementer . Image = NULL; } break; case STRING_KIND: node -> Special . String . Picker = NULL; break; case TEXT_KIND: node -> Special . Text . Picker = NULL; break; case INTEGER_KIND: node -> Special . Integer . LeftIncrementer = NULL; node -> Special . Integer . RightIncrementer = NULL; break; } } gadget = gadget -> NextGadget; } FreeGadgets(handle -> List); handle -> List = NULL; LTK_Free(handle,handle -> GadgetArray,sizeof(struct Gadget *) * handle -> Count); handle -> GadgetArray = NULL; handle -> Count = handle -> Index = 0; LTK_ResetGroups(handle -> TopGroup); if(!bounds) { LTK_GetDisplayClip(handle -> Screen,&newBounds . Left,&newBounds . Top,&newBounds . Width,&newBounds . Height); bounds = &newBounds; } left = handle -> Window -> BorderLeft + handle -> InterWidth; top = handle -> Window -> BorderTop + handle -> InterHeight; LTK_CreateGadgets(handle,bounds,left,top,left + handle -> InterWidth + handle -> Screen -> WBorRight,top + handle -> InterHeight + handle -> Screen -> WBorBottom); if(handle -> Failed) return(FALSE); if(clear) { LTK_SetPens(&handle -> RPort,handle -> BackgroundPen,0,JAM1); RectFill(&handle -> RPort,handle -> Window -> BorderLeft,handle -> Window -> BorderTop,handle -> Window -> Width - (handle -> Window -> BorderRight + 1),handle -> Window -> Height - (handle -> Window -> BorderBottom + 1)); } LTK_AddGadgets(handle); handle -> Previous = NULL; for(i = 0 ; i < handle -> Count ; i++) { if(handle -> GadgetArray[i]) { if(GETOBJECT(handle -> GadgetArray[i],node)) { if(LIKE_STRING_KIND(node) || (node -> Type == INTEGER_KIND)) { if(!handle -> Previous) handle -> Previous = handle -> GadgetArray[i]; } } } } return(TRUE); } else return(FALSE); } /*****************************************************************************/ VOID LIBENT LT_HandleInput(REG(a0) LayoutHandle *Handle,REG(d0) ULONG MsgQualifier,REG(a1) ULONG *MsgClass,REG(a2) UWORD *MsgCode,REG(a3) struct Gadget **MsgGadget) { ObjectNode *Node; BOOLEAN Activate = FALSE; if(!Handle) return; switch(*MsgClass) { case IDCMP_REFRESHWINDOW: if(Handle -> AutoRefresh) { LT_BeginRefresh(Handle); LT_EndRefresh(Handle,TRUE); *MsgClass = NULL; } break; case IDCMP_INTUITICKS: if(Handle -> ActiveIncrementer) { Handle -> IncrementerCountdown--; if(Handle -> IncrementerCountdown <= 0) { if(Handle -> ActiveIncrementer -> Host -> Flags & GFLG_SELECTED) { struct ObjectNode *Parent; LONG Number; *MsgClass = IDCMP_GADGETUP; *MsgCode = 0; *MsgGadget = Handle -> ActiveIncrementer -> Special . Incrementer . Parent; Parent = (*MsgGadget) -> UserData; if(Parent -> Special . Integer . IncrementerHook) Number = CallHookPkt(Parent -> Special . Integer . IncrementerHook,(APTR)LT_GetAttributes(Handle,Parent -> ID,TAG_DONE),Handle -> ActiveIncrementer -> Special . Incrementer . Amount < 0 ? (APTR)INCREMENTERMSG_DECREMENT : (APTR)INCREMENTERMSG_INCREMENT); else Number = ((LONG)LT_GetAttributes(Handle,Parent -> ID,TAG_DONE)) + Handle -> ActiveIncrementer -> Special . Incrementer . Amount; if(Number >= Parent -> Special . Integer . Min && Number <= Parent -> Special . Integer . Max) LT_SetAttributes(Handle,Parent -> ID,GTIN_Number,Number,TAG_DONE); } Handle -> IncrementerCountdown = 2; } } break; case IDCMP_RAWKEY: { UBYTE Buffer[10],Key; struct InputEvent event; BOOLEAN KeyUp; if(*MsgCode == 95 && Handle -> HelpHook) { ObjectNode *Item; struct HelpMsg Message; struct IBox Box; if(Item = LTK_FindNode_Position(Handle -> TopGroup,Handle -> Window -> MouseX,Handle -> Window -> MouseY)) { Message . ObjectID = Item -> ID; Box . Left = Item -> Left; Box . Top = Item -> Top; Box . Width = Item -> Width; Box . Height = Item -> Height; } else { Message . ObjectID = -1; Box . Left = 0; Box . Top = 0; Box . Width = Handle -> Window -> Width; Box . Height = Handle -> Window -> Height; } Message . Handle = Handle; CallHookPkt(Handle -> HelpHook,&Message,&Box); *MsgClass = NULL; break; } if((*MsgCode >= 99 && *MsgCode <= 103) || *MsgCode == 96 || *MsgCode == 97) { *MsgClass = NULL; break; } event . ie_NextEvent = NULL; event . ie_Code = (*MsgCode) & ~IECODE_UP_PREFIX; event . ie_Qualifier = MsgQualifier & ~QUALIFIER_SHIFT; event . ie_Class = IECLASS_RAWKEY; event . ie_SubClass = 0; event . ie_position . ie_addr = (APTR)*MsgGadget; Buffer[0] = 0; if(MapRawKey(&event,Buffer,9,NULL) < 1) { *MsgClass = NULL; break; } if(!(Key = Buffer[0])) { *MsgClass = NULL; break; } if((*MsgCode) & IECODE_UP_PREFIX) KeyUp = TRUE; else KeyUp = FALSE; if(!KeyUp && Handle -> CursorKey && (*MsgCode == CURSORUP || *MsgCode == CURSORDOWN)) { ObjectNode *Node; struct Gadget *Gadget; LONG NewState; Node = Handle -> CursorKey; Gadget = Node -> Host; NewState = Node -> Current; if(*MsgCode == CURSORDOWN) { if(MsgQualifier & QUALIFIER_SHIFT) NewState += Node -> Lines; else { if(MsgQualifier & (QUALIFIER_ALT | QUALIFIER_CONTROL)) NewState = Node -> Max; else NewState++; } } else { if(MsgQualifier & QUALIFIER_SHIFT) NewState -= Node -> Lines; else { if(MsgQualifier & (QUALIFIER_ALT | QUALIFIER_CONTROL)) NewState = Node -> Min; else NewState--; } } if(NewState < Node -> Min) NewState = Node -> Min; else { if(NewState > Node -> Max) NewState = Node -> Max; } if(NewState != Node -> Current && Node -> Max != Node -> Min) { Node -> Current = NewState; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTLV_Top, Node -> Current, GTLV_MakeVisible, Node -> Current, Node -> Special . List . LinkID != -1 ? GTLV_Selected : TAG_IGNORE,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; return; } if(Key == '\33' && !KeyUp) { ObjectNode *Node; if(Node = Handle -> EscKey) { if(!Node -> Disabled) { LTK_BlinkButton(Handle,Node -> Host); *MsgCode = 0; *MsgGadget = Node -> Host; *MsgClass = IDCMP_GADGETUP; } else *MsgClass = NULL; return; } if(Handle -> Window -> Flags & WFLG_CLOSEGADGET) { *MsgCode = 0; *MsgGadget = NULL; *MsgClass = IDCMP_CLOSEWINDOW; } else *MsgClass = NULL; return; } else { struct Gadget *Gadget; ObjectNode *Node; LONG i; BOOLEAN FoundIt = FALSE, Forward; if(MsgQualifier & QUALIFIER_SHIFT) Forward = FALSE; else Forward = TRUE; if(Handle -> ReturnKey && Key == '\r') { Node = Handle -> ReturnKey; if(!KeyUp && !Node -> Disabled) { LTK_BlinkButton(Handle,Node -> Host); *MsgClass = IDCMP_GADGETUP; *MsgCode = 0; *MsgGadget = Node -> Host; } else *MsgClass = NULL; return; } for(i = 0 ; !FoundIt && i < Handle -> Count ; i++) { if(Gadget = Handle -> GadgetArray[i]) { if(GETOBJECT(Gadget,Node)) { if(Key == Node -> Key) { if(Node -> Disabled) break; else { switch(Node -> Type) { #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: if(!(MsgQualifier & IEQUALIFIER_REPEAT)) { if(Node -> Special . TapeDeck . Toggle) { LT_SetAttributes(Handle,Node -> ID, LATD_Pressed,!Node -> Current, TAG_DONE); LTK_PutStorage(Node); } if(Gadget -> Flags & GFLG_SELECTED) *MsgCode = TRUE; else *MsgCode = FALSE; *MsgClass = IDCMP_GADGETUP; *MsgGadget = Gadget; } else *MsgClass = NULL; break; #endif /* DO_TAPEDECK_KIND */ case CHECKBOX_KIND: if(!KeyUp && !(MsgQualifier & IEQUALIFIER_REPEAT)) { Node -> Current = !Node -> Current; LTK_PutStorage(Node); GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTCB_Checked,Node -> Current, TAG_DONE); *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; FoundIt = TRUE; break; case LISTVIEW_KIND: if(!KeyUp) { BOOLEAN setAttrs = FALSE; if(Forward) { if(Node -> Current < Node -> Max) { Node -> Current++; setAttrs = TRUE; } } else { if(Node -> Current > Node -> Min) { Node -> Current--; setAttrs = TRUE; } } if(setAttrs) { if(Node -> Current < 0) { GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTLV_Selected,Node -> Current, TAG_DONE); } else { GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTLV_Top, Node -> Current, GTLV_MakeVisible, Node -> Current, Node -> Special . List . LinkID != -1 ? GTLV_Selected : TAG_IGNORE,Node -> Current, TAG_DONE); } LTK_PutStorage(Node); *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } else *MsgClass = NULL; FoundIt = TRUE; break; case MX_KIND: if(!KeyUp) { if(Forward) { if(Node -> Current < Node -> Max) { Node -> Current++; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTMX_Active,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_GADGETDOWN; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } else { if(Node -> Current > Node -> Min) { Node -> Current--; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTMX_Active,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_GADGETDOWN; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } } else *MsgClass = NULL; FoundIt = TRUE; break; case TEXT_KIND: if(!KeyUp && !(MsgQualifier & IEQUALIFIER_REPEAT)) { if(Node -> Special . Text . Picker) { LTK_BlinkButton(Handle,Node -> Special . Text . Picker); *MsgClass = IDCMP_IDCMPUPDATE; *MsgCode = 0; *MsgGadget = Gadget; } else *MsgClass = NULL; } else *MsgClass = NULL; FoundIt = TRUE; break; case NUMBER_KIND: *MsgClass = NULL; FoundIt = TRUE; break; case CYCLE_KIND: if(!KeyUp && !(MsgQualifier & IEQUALIFIER_REPEAT)) { LTK_BlinkButton(Handle,Gadget); if(Forward) { if(Node -> Current < Node -> Max) Node -> Current++; else Node -> Current = Node -> Min; } else { if(Node -> Current > Node -> Min) Node -> Current--; else Node -> Current = Node -> Max; } LTK_PutStorage(Node); GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTCY_Active,Node -> Current, TAG_DONE); *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; FoundIt = TRUE; break; case PALETTE_KIND: if(!KeyUp) { if(Forward) { if(Node -> Current < Node -> Max) Node -> Current++; else Node -> Current = Node -> Min; } else { if(Node -> Current > Node -> Min) Node -> Current--; else Node -> Current = Node -> Max; } LTK_PutStorage(Node); GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTPA_Color,Node -> Current, TAG_DONE); *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; FoundIt = TRUE; break; case SLIDER_KIND: if(KeyUp) { *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else { if(Forward) { if(Node -> Current < Node -> Max) { Node -> Current++; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTSL_Level,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_MOUSEMOVE; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } else { if(Node -> Current > Node -> Min) { Node -> Current--; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTSL_Level,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_MOUSEMOVE; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } } FoundIt = TRUE; break; case SCROLLER_KIND: if(KeyUp) { *MsgClass = IDCMP_GADGETUP; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else { if(Forward) { if(Node -> Current < Node -> Max) { Node -> Current++; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTSC_Top,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_MOUSEMOVE; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } else { if(Node -> Current > Node -> Min) { Node -> Current--; GT_SetGadgetAttrs(Gadget,Handle -> Window,NULL, GTSC_Top,Node -> Current, TAG_DONE); LTK_PutStorage(Node); *MsgClass = IDCMP_MOUSEMOVE; *MsgCode = Node -> Current; *MsgGadget = Gadget; } else *MsgClass = NULL; } } FoundIt = TRUE; break; case STRING_KIND: case FRACTION_KIND: case PASSWORD_KIND: if(!KeyUp) { if(Node -> Special . String . Picker && !Forward) { LTK_BlinkButton(Handle,Node -> Special . String . Picker); *MsgClass = IDCMP_IDCMPUPDATE; *MsgCode = 0; *MsgGadget = Gadget; } else { ActivateGadget(Gadget,Handle -> Window,NULL); *MsgClass = IDCMP_GADGETDOWN; *MsgCode = 0; *MsgGadget = Gadget; Handle -> Previous = Gadget; } } else *MsgClass = NULL; FoundIt = TRUE; break; case INTEGER_KIND : if(!KeyUp) { if(Node -> Special . Integer . UseIncrementers) { ObjectNode *incNode,*Parent = (ObjectNode *)Gadget -> UserData; LONG Number; struct Gadget *Incrementer; if(Forward) { incNode = Node -> Special . Integer . RightIncrementer -> UserData; Incrementer = Node -> Special . Integer . RightIncrementer; } else { incNode = Node -> Special . Integer . LeftIncrementer -> UserData; Incrementer = Node -> Special . Integer . LeftIncrementer; } if(Parent -> Special . Integer . IncrementerHook) Number = CallHookPkt(Parent -> Special . Integer . IncrementerHook,(APTR)LT_GetAttributes(Handle,Parent -> ID,TAG_DONE),incNode -> Special . Incrementer . Amount < 0 ? (APTR)INCREMENTERMSG_DECREMENT : (APTR)INCREMENTERMSG_INCREMENT); else Number = LT_GetAttributes(Handle,Parent -> ID,TAG_DONE) + incNode -> Special . Incrementer . Amount; if(Number >= Parent -> Special . Integer . Min && Number <= Parent -> Special . Integer . Max) { LTK_BlinkButton(Handle,Incrementer); LT_SetAttributes(Handle,Parent -> ID,GTIN_Number,Number,TAG_DONE); *MsgClass = IDCMP_GADGETUP; LTK_PutStorage(Node); } } else { ActivateGadget(Gadget,Handle -> Window,NULL); *MsgClass = IDCMP_GADGETDOWN; } *MsgCode = 0; *MsgGadget = Gadget; Handle -> Previous = Gadget; } else *MsgClass = NULL; FoundIt = TRUE; break; case BUTTON_KIND: if(!KeyUp && !(MsgQualifier & IEQUALIFIER_REPEAT)) { LTK_BlinkButton(Handle,Gadget); *MsgClass = IDCMP_GADGETUP; *MsgCode = 0; *MsgGadget = Gadget; } else *MsgClass = NULL; FoundIt = TRUE; break; } } } } } } } break; } case IDCMP_GADGETDOWN: if(GETOBJECT((*MsgGadget),Node)) { switch(Node -> Type) { case STRING_KIND: case INTEGER_KIND: case FRACTION_KIND: case PASSWORD_KIND: Handle -> Previous = *MsgGadget; break; #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: if(Node -> Special . TapeDeck . Toggle) { if((*MsgGadget) -> Flags & GFLG_SELECTED) *MsgCode = TRUE; else *MsgCode = FALSE; Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; *MsgClass = IDCMP_GADGETUP; } else *MsgClass = NULL; break; #endif /* DO_TAPEDECK_KIND */ case MX_KIND: if(!V39 && Node -> Disabled) { GT_SetGadgetAttrs(*MsgGadget,Handle -> Window,NULL, GTMX_Active,Node -> Current, TAG_DONE); *MsgClass = NULL; } else { Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; } break; case SLIDER_KIND: if(Node -> Min < 0) Node -> Current = (WORD)*MsgCode; else Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case SCROLLER_KIND: Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case INCREMENTER_KIND: Handle -> ActiveIncrementer = Node; Handle -> IncrementerCountdown = 6; *MsgClass = IDCMP_GADGETUP; *MsgCode = 0; *MsgGadget = Node -> Special . Incrementer . Parent; /* ALWAYS */ { struct ObjectNode *Parent = (ObjectNode *)(*MsgGadget) -> UserData; LONG Number; if(Parent -> Special . Integer . IncrementerHook) Number = CallHookPkt(Parent -> Special . Integer . IncrementerHook,(APTR)LT_GetAttributes(Handle,Parent -> ID,TAG_DONE),Node -> Special . Incrementer . Amount < 0 ? (APTR)INCREMENTERMSG_DECREMENT : (APTR)INCREMENTERMSG_INCREMENT); else Number = LT_GetAttributes(Handle,Parent -> ID,TAG_DONE) + Node -> Special . Incrementer . Amount; if(Number >= Parent -> Special . Integer . Min && Number <= Parent -> Special . Integer . Max) LT_SetAttributes(Handle,Parent -> ID,GTIN_Number,Number,TAG_DONE); else *MsgClass = NULL; } break; } } break; case IDCMP_MOUSEBUTTONS: if(((*MsgCode) & IECODE_UP_PREFIX) && Handle -> Previous) Activate = TRUE; if((*MsgCode == SELECTUP) && (Handle -> ActiveIncrementer)) Handle -> ActiveIncrementer = NULL; break; case IDCMP_GADGETUP: if(GETOBJECT((*MsgGadget),Node)) { switch(Node -> Type) { case FRACTION_KIND: LT_SetAttributes(Handle,(*MsgGadget) -> GadgetID,LAFC_Number,LT_GetAttributes(Handle,(*MsgGadget) -> GadgetID,TAG_DONE),TAG_DONE); /* FALLS THROUGH */ case PASSWORD_KIND: case STRING_KIND: Handle -> Previous = NULL; LTK_PutStorage(Node); break; case INTEGER_KIND: { struct StringInfo *StringInfo = (struct StringInfo *)(*MsgGadget) -> SpecialInfo; LONG Contents = StringInfo -> LongInt; if(Contents < Node -> Special . Integer . Min) Contents = Node -> Special . Integer . Min; else { if(Contents > Node -> Special . Integer . Max) Contents = Node -> Special . Integer . Max; } LT_SetAttributes(Handle,(*MsgGadget) -> GadgetID,GTIN_Number,Contents,TAG_DONE); Handle -> Previous = NULL; LTK_PutStorage(Node); break; } case CHECKBOX_KIND: if(!V39) { if((*MsgGadget) -> Flags & GFLG_SELECTED) *MsgCode = TRUE; else *MsgCode = FALSE; } Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: if(Node -> Special . TapeDeck . Toggle) { if((*MsgGadget) -> Flags & GFLG_SELECTED) *MsgCode = TRUE; else *MsgCode = FALSE; Node -> Current = *MsgCode; LTK_PutStorage(Node); } if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; #endif /* DO_TAPEDECK_KIND */ case CYCLE_KIND: case PALETTE_KIND: Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case MX_KIND: if(!V39 && Node -> Disabled) { GT_SetGadgetAttrs(*MsgGadget,Handle -> Window,NULL, GTMX_Active,Node -> Current, TAG_DONE); *MsgClass = NULL; } else { Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; } break; case SLIDER_KIND: if(Node -> Min < 0) Node -> Current = (WORD)*MsgCode; else Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case SCROLLER_KIND: Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case PICKER_KIND: *MsgClass = IDCMP_IDCMPUPDATE; *MsgCode = 0; *MsgGadget = Node -> Special . Picker . Parent; if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; case INCREMENTER_KIND: Handle -> ActiveIncrementer = NULL; break; case LISTVIEW_KIND: if(Node -> Current != *MsgCode) CurrentTime(&Node -> Special . List . ClickSeconds,&Node -> Special . List . ClickMicros); else { ULONG Seconds,Micros; CurrentTime(&Seconds,&Micros); if(DoubleClick(Node -> Special . List . ClickSeconds,Node -> Special . List . ClickMicros,Seconds,Micros)) *MsgClass = IDCMP_IDCMPUPDATE; Node -> Special . List . ClickSeconds = Seconds; Node -> Special . List . ClickMicros = Micros; } Node -> Current = *MsgCode; LTK_PutStorage(Node); if(Node -> Special . List . Link) { Handle -> Previous = Node -> Special . List . Link; if(!Node -> PageSelector) Activate = TRUE; } else { if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; } break; default: if(Handle -> Previous && !Node -> PageSelector) Activate = TRUE; break; } } break; case IDCMP_MOUSEMOVE: if(GETOBJECT((*MsgGadget),Node)) { if(Node -> Type == SLIDER_KIND) { if(Node -> Min < 0) Node -> Current = (WORD)*MsgCode; else Node -> Current = *MsgCode; LTK_PutStorage(Node); } else { if(Node -> Type == SCROLLER_KIND) { Node -> Current = *MsgCode; LTK_PutStorage(Node); } } } break; case IDCMP_ACTIVEWINDOW: if(Handle -> Previous) { Activate = TRUE; *MsgClass = IDCMP_GADGETDOWN; *MsgCode = 0; *MsgGadget = Handle -> Previous; } break; case IDCMP_INACTIVEWINDOW: Handle -> ActiveIncrementer = NULL; break; } if(Handle -> AutoActivate && Activate && Handle -> Previous) { if(GETOBJECT(Handle -> Previous,Node)) { if(!Node -> Disabled) ActivateGadget(Handle -> Previous,Handle -> Window,NULL); } } } /*****************************************************************************/ VOID LIBENT LT_BeginRefresh(REG(a0) LayoutHandle *handle) { if(handle) { GT_BeginRefresh(handle -> Window); LTK_DrawGroup(handle,handle -> TopGroup); } } /*****************************************************************************/ VOID LIBENT LT_EndRefresh(REG(a0) LayoutHandle *handle,REG(d0) BOOL complete) { if(handle) GT_EndRefresh(handle -> Window,complete); } /*****************************************************************************/ LONG __stdargs LT_GetAttributes(LayoutHandle *Handle,LONG ID,...) { va_list VarArgs; LONG Result; va_start(VarArgs,ID); Result = LT_GetAttributesA(Handle,ID,(struct TagItem *)VarArgs); va_end(VarArgs); return(Result); } LONG LIBENT LT_GetAttributesA(REG(a0) LayoutHandle *Handle,REG(d0) LONG ID,REG(a1) struct TagItem *TagList) { if(Handle) { ObjectNode *Node; if(Node = LTK_FindNode(Handle -> TopGroup,ID)) { struct StringInfo *StringInfo; if(TagList) { struct TagItem *TagItem, *TempPtr = TagList; LONG *Value; while(TagItem = NextTagItem(&TempPtr)) { Value = (LONG *)TagItem -> ti_Data; switch(TagItem -> ti_Tag) { case LA_Left: if(Node -> Type == FRAME_KIND && Node -> Special . Frame . DrawBox) *Value = Node -> Left + 4; else *Value = Node -> Left; break; case LA_Top: if(Node -> Type == FRAME_KIND && Node -> Special . Frame . DrawBox) *Value = Node -> Top + 2; else *Value = Node -> Top; break; case LA_Width: if(Node -> Type == FRAME_KIND && Node -> Special . Frame . DrawBox) *Value = Node -> Width - 8; else *Value = Node -> Width; break; case LA_Height: if(Node -> Type == FRAME_KIND && Node -> Special . Frame . DrawBox) *Value = Node -> Height - 4; else *Value = Node -> Height; break; } } } if(Node -> Host) { struct Gadget *Gadget = Node -> Host; switch(Node -> Type) { case CHECKBOX_KIND: case LISTVIEW_KIND: case MX_KIND: case CYCLE_KIND: case PALETTE_KIND: case SLIDER_KIND: case SCROLLER_KIND: #ifdef DO_GAUGE_KIND case GAUGE_KIND: #endif #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: #endif /* DO_TAPEDECK_KIND */ return(Node -> Current); #ifdef DO_FRACTION_KIND case FRACTION_KIND: { FIXED Contents; StringInfo = (struct StringInfo *)Gadget -> SpecialInfo; Contents = LT_String2Fixed(StringInfo -> Buffer); if(Contents < Node -> Special . String . Min) Contents = Node -> Special . String . Min; else { if(Contents > Node -> Special . String . Max) Contents = Node -> Special . String . Max; } LT_SetAttributes(Handle,Gadget -> GadgetID,LAFC_Number,Contents,TAG_DONE); return((LONG)Contents); } #endif case STRING_KIND: StringInfo = (struct StringInfo *)Gadget -> SpecialInfo; return((LONG)StringInfo -> Buffer); #ifdef DO_PASSWORD_KIND case PASSWORD_KIND: return((LONG)Node -> Special . String . Original); #endif case INTEGER_KIND: { LONG Contents; StringInfo = (struct StringInfo *)Gadget -> SpecialInfo; Contents = StringInfo -> LongInt; if(Contents < Node -> Special . Integer . Min) LT_SetAttributes(Handle,Gadget -> GadgetID,GTIN_Number,Contents = Node -> Special . Integer . Min,TAG_DONE); else { if(Contents > Node -> Special . Integer . Max) LT_SetAttributes(Handle,Gadget -> GadgetID,GTIN_Number,Contents = Node -> Special . Integer . Max,TAG_DONE); else Node -> Special . Integer . Number = Contents; } return(Contents); } case GROUP_KIND: return((LONG)Node -> Special . Group . ActivePage); } } } } return(NULL); } /*****************************************************************************/ VOID __stdargs LT_SetAttributes(LayoutHandle *handle,LONG id,...) { va_list VarArgs; va_start(VarArgs,id); LT_SetAttributesA(handle,id,(struct TagItem *)VarArgs); va_end(VarArgs); } VOID LIBENT LT_SetAttributesA(REG(a0) LayoutHandle *handle,REG(d0) LONG id,REG(a1) struct TagItem *TagList) { if(handle && TagList) { struct Gadget *Gadget; struct TagItem *ThisTag; ObjectNode *Node; if(ThisTag = FindTagItem(LH_AutoActivate,TagList)) handle -> AutoActivate = ThisTag -> ti_Data; if(ThisTag = FindTagItem(LH_LocaleHook,TagList)) handle -> LocaleHook = (struct Hook *)ThisTag -> ti_Data; if(Gadget = LTK_FindGadget(handle,id)) { if(Node = (ObjectNode *)Gadget -> UserData) { if(Node -> Host != Gadget || Node -> PointBack != Node) Node = NULL; } } else Node = LTK_FindNode(handle -> TopGroup,id); if(Node) { STATIC Tag Filter[] = { GA_Disabled,TAG_DONE }; struct TagItem *NewTags = NULL; ULONG Exclude = NULL; switch(Node -> Type) { case CHECKBOX_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTCB_Checked,TagList)) { if((Node -> Current && ThisTag -> ti_Data) || (!Node -> Current && !ThisTag -> ti_Data)) Exclude = GTCB_Checked; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } break; #ifdef DO_TAPEDECK_KIND case TAPEDECK_KIND: if(Gadget) { if(ThisTag = FindTagItem(LATD_Pressed,TagList)) { if(Node -> Current != ThisTag -> ti_Data && Node -> Special . TapeDeck . Toggle) { RemoveGList(handle -> Window,handle -> List,(UWORD)-1); if(Node -> Current = ThisTag -> ti_Data) Gadget -> Flags |= GFLG_SELECTED; else Gadget -> Flags &= ~GFLG_SELECTED; AddGList(handle -> Window,handle -> List,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(Gadget,handle -> Window,NULL,1); } } } break; #endif /* DO_TAPEDECK_KIND */ #ifdef DO_GAUGE_KIND case GAUGE_KIND: if(Gadget) { LONG Percent = (LONG)Node -> Current; BOOLEAN NeedRefresh = FALSE; if(ThisTag = FindTagItem(LAGA_Percent,TagList)) { Percent = (LONG)ThisTag -> ti_Data; if(Percent < 0) Percent = 0; else { if(Percent > 100) Percent = 100; } if(Percent != (LONG)Node -> Current) NeedRefresh = TRUE; } if(ThisTag = FindTagItem(LAGA_InfoText,TagList)) { STRPTR SomeText = (STRPTR)ThisTag -> ti_Data; if(Node -> Special . Gauge . InfoLength) { LONG Len = strlen(SomeText); if(Len > Node -> Special . Gauge . InfoLength) Len = Node -> Special . Gauge . InfoLength; CopyMem(SomeText,Node -> Special . Gauge . InfoText,Len); Node -> Special . Gauge . InfoText[Len] = 0; NeedRefresh = TRUE; } } if(NeedRefresh) LTK_DrawGauge(handle,Node,Percent,FALSE); } return; #endif case LISTVIEW_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTLV_Labels,TagList)) { if(ThisTag -> ti_Data == (ULONG)~0) Node -> Min = Node -> Max = -1; else { struct List *List; LONG Count = 0; if(List = (struct List *)ThisTag -> ti_Data) { struct Node *Item; SCANLIST(List,Item) { Count++; } } Node -> Min = 0; if(Count) Node -> Max = Count - 1; else Node -> Max = 0; } } if(ThisTag = FindTagItem(GA_Disabled,TagList)) { if(!V39) { if(!(NewTags = CloneTagItems(TagList))) return; else FilterTagItems(NewTags,Filter,TAGFILTER_NOT); } } if(ThisTag = FindTagItem(GTLV_Selected,TagList)) { struct List *List; Node -> Current = (LONG)ThisTag -> ti_Data; if(ThisTag = FindTagItem(GTLV_Labels,TagList)) List = (struct List *)ThisTag -> ti_Data; else List = NULL; if(Node -> Current < 0) { GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GTLV_Selected, Node -> Current, List ? GTLV_Labels : TAG_IGNORE,List, TAG_DONE); } else { GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GTLV_Selected, Node -> Current, GTLV_Top, Node -> Current, GTLV_MakeVisible, Node -> Current, List ? GTLV_Labels : TAG_IGNORE,List, TAG_DONE); } LTK_PutStorage(Node); } break; case MX_KIND: if(!Gadget) return; if(!V39) { if(FindTagItem(GA_Disabled,TagList)) { if(!(NewTags = CloneTagItems(TagList))) return; else FilterTagItems(NewTags,Filter,TAGFILTER_NOT); } } if(ThisTag = FindTagItem(GTMX_Active,TagList)) { if(Node -> Current == ThisTag -> ti_Data) Exclude = GTMX_Active; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } break; case CYCLE_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTCY_Active,TagList)) { if(Node -> Current == ThisTag -> ti_Data) Exclude = GTCY_Active; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } if(ThisTag = FindTagItem(GTCY_Labels,TagList)) { STRPTR *Strings; LONG Count = 0; if(Strings = (STRPTR *)ThisTag -> ti_Data) { while(Strings[Count]) Count++; } if(Count) Node -> Max = Count - 1; else Node -> Max = 0; } break; case PALETTE_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTPA_Color,TagList)) { if(Node -> Current == ThisTag -> ti_Data) Exclude = GTPA_Color; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } break; case INTEGER_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTIN_Number,TagList)) { LONG num; num = ThisTag -> ti_Data; if(num < Node -> Special . Integer . Min) num = Node -> Special . Integer . Min; else { if(num > Node -> Special . Integer . Max) num = Node -> Special . Integer . Max; } #ifdef DO_HEXHOOK if(!Node -> Special . Integer . EditHook) { UBYTE buffer[20]; struct StringInfo *stringInfo; sprintf(buffer,"%ld",num); Exclude = GTIN_Number; GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GTST_String,buffer, TAG_DONE); stringInfo = (struct StringInfo *)Gadget -> SpecialInfo; stringInfo -> LongInt = num; } else { UBYTE buffer[40]; struct StringInfo *stringInfo; STRPTR Index; LONG Value,Number = num, Scale,Sign; stringInfo = (struct StringInfo *)Gadget -> SpecialInfo; Index = stringInfo -> Buffer; while(*Index && *Index == ' ') Index++; switch(Index[0]) { case '$': sprintf(buffer,"$%lx",num); break; case '&': if(Number < 0) { Sign = -1; Number = -Number; } else Sign = 1; for(Value = 0, Scale = 1 ; Number ; Number /= 8, Scale *= 10) Value += (Number & 7) * Scale; sprintf(buffer,"&%ld",Sign * Value); break; case '%': if(Number < 0) { Sign = -1; Number = -Number; } else Sign = 1; for(Value = 0, Scale = 1 ; Number ; Number /= 2, Scale *= 10) Value += (Number & 1) * Scale; sprintf(buffer,"%%%ld",Sign * Value); break; case '0': if(Index[1] == 'x') { sprintf(buffer,"0x%lx",num); break; } // Fall through to... default: sprintf(buffer,"%ld",num); break; } Exclude = GTIN_Number; GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GTST_String,buffer, TAG_DONE); stringInfo -> LongInt = num; } #else GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GTIN_Number,num, TAG_DONE); #endif Node -> Special . Integer . Number = num; LTK_PutStorage(Node); } break; case SLIDER_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTSL_Level,TagList)) { if(Node -> Current == ThisTag -> ti_Data) Exclude = GTSL_Level; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } if(ThisTag = FindTagItem(GTSL_Min,TagList)) { Node -> Min = ThisTag -> ti_Data; if(Node -> Current < Node -> Min) { Node -> Current = Node -> Min; LTK_PutStorage(Node); } } if(ThisTag = FindTagItem(GTSL_Max,TagList)) { Node -> Max = ThisTag -> ti_Data; if(Node -> Current > Node -> Max) { Node -> Current = Node -> Max; LTK_PutStorage(Node); } } break; case SCROLLER_KIND: if(!Gadget) return; if(ThisTag = FindTagItem(GTSC_Top,TagList)) { if(Node -> Current == ThisTag -> ti_Data) Exclude = GTSC_Top; else { Node -> Current = ThisTag -> ti_Data; LTK_PutStorage(Node); } } if(ThisTag = FindTagItem(GTSC_Total,TagList)) { Node -> Max = ThisTag -> ti_Data; if(Node -> Current > Node -> Max) { Node -> Current = Node -> Max; LTK_PutStorage(Node); } } if(ThisTag = FindTagItem(GTSC_Visible,TagList)) Node -> Special . Scroller . Visible = ThisTag -> ti_Data; break; case BOX_KIND: if(ThisTag = FindTagItem(LABX_Index,TagList)) { LONG Index = ThisTag -> ti_Data; if(Index >= 0 && Index < Node -> Lines) { if(ThisTag = FindTagItem(LABX_Text,TagList)) { if(Node -> Special . Box . ReserveSpace) { STRPTR Text = (STRPTR)ThisTag -> ti_Data; WORD Len = strlen(Text); if(Len > Node -> Special . Box . MaxSize) Len = Node -> Special . Box . MaxSize; CopyMem(Text,Node -> Special . Box . Lines[Index],Len); Node -> Special . Box . Lines[Index][Len] = 0; } else Node -> Special . Box . Lines[Index] = (STRPTR)ThisTag -> ti_Data; LTK_PrintBoxLine(handle,Node,Index); } } } if(ThisTag = FindTagItem(LABX_Lines,TagList)) { STRPTR *Lines = (STRPTR *)ThisTag -> ti_Data; LONG i; if(Node -> Special . Box . ReserveSpace) { WORD Len; for(i = 0 ; i < Node -> Lines ; i++) { if(Lines[i]) { Len = strlen(Lines[i]); if(Len > Node -> Special . Box . MaxSize) Len = Node -> Special . Box . MaxSize; CopyMem(Lines[i],Node -> Special . Box . Lines[i],Len); Node -> Special . Box . Lines[i][Len] = 0; LTK_PrintBoxLine(handle,Node,i); } else break; } } else { for(i = 0 ; i < Node -> Lines ; i++) { if(Lines[i]) { Node -> Special . Box . Lines[i] = Lines[i]; LTK_PrintBoxLine(handle,Node,i); } else break; } } } break; case GROUP_KIND: if(Node -> Special . Group . Paging) { if(ThisTag = FindTagItem(LAGR_ActivePage,TagList)) { ObjectNode *node; if(node = LTK_FindNode(handle -> TopGroup,id)) { if(node -> Type == GROUP_KIND) { if(node -> Special . Group . ActivePage != ThisTag -> ti_Data) { node -> Special . Group . ActivePage = ThisTag -> ti_Data; LTK_SetPens(&handle -> RPort,handle -> BackgroundPen,0,JAM1); RectFill(&handle -> RPort,node -> Left,node -> Top,node -> Left+node -> Width - 1,node -> Top + node -> Height - 1); LT_Rebuild(handle,NULL,0,0,FALSE); } } } } } break; } if(ThisTag = FindTagItem(LA_LabelText,TagList)) Node -> Label = (STRPTR)ThisTag -> ti_Data; if(ThisTag = FindTagItem(LA_LabelID,TagList)) { if(handle -> LocaleHook) Node -> Label = (STRPTR)CallHookPkt(handle -> LocaleHook,handle,(APTR)ThisTag -> ti_Data); } if(ThisTag = FindTagItem(GA_Disabled,TagList)) { if((Node -> Disabled && ThisTag -> ti_Data) || (!Node -> Disabled && !ThisTag -> ti_Data)) { if(NewTags = CloneTagItems(TagList)) FilterTagItems(NewTags,Filter,TAGFILTER_NOT); } else { struct Gadget *gad; Node -> Disabled = ThisTag -> ti_Data; switch(Node -> Type) { case TEXT_KIND: gad = Node -> Special . Text . Picker; break; case STRING_KIND: gad = Node -> Special . String . Picker; break; case INTEGER_KIND: if(gad = Node -> Special . Integer . LeftIncrementer) { RemoveGList(handle -> Window,handle -> List,(UWORD)-1); if(Node -> Disabled) gad -> Flags |= GFLG_DISABLED; else gad -> Flags &= ~GFLG_DISABLED; AddGList(handle -> Window,handle -> List,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(gad,handle -> Window,NULL,1); } gad = Node -> Special . Integer . RightIncrementer; break; case TAPEDECK_KIND: gad = Node -> Host; Gadget = NULL; break; default: gad = NULL; break; } if(gad) { RemoveGList(handle -> Window,handle -> List,(UWORD)-1); if(Node -> Disabled) gad -> Flags |= GFLG_DISABLED; else gad -> Flags &= ~GFLG_DISABLED; AddGList(handle -> Window,handle -> List,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(gad,handle -> Window,NULL,1); } } } if(Exclude) { ULONG Filter[2]; Filter[0] = Exclude; Filter[1] = TAG_DONE; if(!NewTags) NewTags = CloneTagItems(TagList); if(NewTags) FilterTagItems(NewTags,Filter,TAGFILTER_NOT); } if(Gadget) { struct TagItem *tags = TagList; if(NewTags) tags = NewTags; if(!V39 && Node -> Disabled && Node -> Type == SLIDER_KIND) { GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GA_Disabled, FALSE, TAG_MORE,tags); GT_SetGadgetAttrs(Gadget,handle -> Window,NULL, GA_Disabled, TRUE, TAG_DONE); } else GT_SetGadgetAttrsA(Gadget,handle -> Window,NULL,tags); if(Node -> Type == STRING_KIND || Node -> Type == FRACTION_KIND || Node -> Type == PASSWORD_KIND) LTK_PutStorage(Node); } FreeTagItems(NewTags); } } } /*****************************************************************************/ VOID __stdargs LT_Add(LayoutHandle *Handle,UBYTE Type,STRPTR Label,LONG ID,...) { va_list VarArgs; va_start(VarArgs,ID); LT_AddA(Handle,Type,Label,ID,(struct TagItem *)VarArgs); va_end(VarArgs); } VOID LIBENT LT_AddA(REG(a0) LayoutHandle *Handle,REG(d0) UBYTE Type,REG(d1) STRPTR Label,REG(d2) LONG ID,REG(a1) struct TagItem *TagList) { struct TagItem *TagItem; if(!Handle || Handle -> Failed) return; /* if(ID > Handle -> MaxID)*/ /* Handle -> MaxID = ID + 1;*/ if(Type == VERTICAL_KIND || Type == HORIZONTAL_KIND || Handle -> TopGroup) { ObjectNode *Node; switch(Type) { case BUTTON_KIND: Handle -> IDCMP |= BUTTONIDCMP; break; case CHECKBOX_KIND: Handle -> IDCMP |= CHECKBOXIDCMP; break; case LISTVIEW_KIND: Handle -> IDCMP |= LISTVIEWIDCMP; break; case MX_KIND: Handle -> IDCMP |= MXIDCMP; break; case CYCLE_KIND: Handle -> IDCMP |= CYCLEIDCMP; break; case PALETTE_KIND: Handle -> IDCMP |= PALETTEIDCMP; break; case SLIDER_KIND: Handle -> IDCMP |= SLIDERIDCMP; break; case SCROLLER_KIND: Handle -> IDCMP |= SCROLLERIDCMP | ARROWIDCMP; break; case INTEGER_KIND: Handle -> IDCMP |= STRINGIDCMP | IDCMP_GADGETDOWN | IDCMP_INTUITICKS; break; case STRING_KIND: case FRACTION_KIND: case PASSWORD_KIND: Handle -> IDCMP |= STRINGIDCMP | IDCMP_GADGETDOWN; break; case END_KIND: Handle -> CurrentGroup = Handle -> CurrentGroup -> Special . Group . ParentGroup; return; } if(Node = LTK_CreateObjectNode(Handle,Type,ID,Label)) { struct MinList *ParentList; LONG FirstLabel = -1; LONG LastLabel = -1; Type = Node -> Type; if(Type == GROUP_KIND) { Node -> LabelPlace = PLACE_IN; Node -> Special . Group . ParentGroup = Handle -> CurrentGroup; if(!Handle -> TopGroup) { Handle -> TopGroup = Node; ParentList = NULL; } else ParentList = &Handle -> CurrentGroup -> Special . Group . ObjectList; Handle -> CurrentGroup = Node; NewList(&Node -> Special . Group . ObjectList); } else ParentList = &Handle -> CurrentGroup -> Special . Group . ObjectList; if(Label && !Node -> NoKey) { ULONG Len; Len = 0; while(Label[Len]) { if(Label[Len] == '_') { Node -> Key = ToLower(Label[Len + 1]); break; } Len++; } } if(TagList) { struct TagItem *TempList = TagList; while(!Handle -> Failed && (TagItem = NextTagItem(&TempList))) { switch(TagItem -> ti_Tag) { case LA_BYTE: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_BYTE; LTK_GetStorage(Node); break; case LA_UBYTE: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_UBYTE; LTK_GetStorage(Node); break; case LA_WORD: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_WORD; LTK_GetStorage(Node); break; case LA_UWORD: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_UWORD; LTK_GetStorage(Node); break; case LA_LONG: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_LONG; LTK_GetStorage(Node); break; case LA_ULONG: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_ULONG; LTK_GetStorage(Node); break; case LA_STRPTR: Node -> Storage = (APTR)TagItem -> ti_Data; Node -> StorageType = STORAGE_STRPTR; LTK_GetStorage(Node); break; case LAXB_FullSize: if(Type == XBAR_KIND || Type == YBAR_KIND) Node -> Special . Bar . FullSize = TagItem -> ti_Data; break; case LA_FirstLabel: FirstLabel = TagItem -> ti_Data; break; case LA_LastLabel: LastLabel = TagItem -> ti_Data; break; case LA_LastGadget: if(Type == INTEGER_KIND) Node -> Special . Integer . LastGadget = TagItem -> ti_Data; else { if(Type == FRACTION_KIND || Type == STRING_KIND || Type == PASSWORD_KIND) Node -> Special . String . LastGadget = TagItem -> ti_Data; } break; case LA_HistoryLines: if(Type == INTEGER_KIND) Node -> Special . Integer . MaxHistoryLines = TagItem -> ti_Data; else { if(Type == FRACTION_KIND || Type == STRING_KIND || Type == PASSWORD_KIND) Node -> Special . String . MaxHistoryLines = TagItem -> ti_Data; } break; case LA_HistoryHook: if(Type == INTEGER_KIND) Node -> Special . Integer . HistoryHook = (struct Hook *)TagItem -> ti_Data; else { if(Type == FRACTION_KIND || Type == STRING_KIND) Node -> Special . String . HistoryHook = (struct Hook *)TagItem -> ti_Data; } break; case LAIN_IncrementerHook: if(Type == INTEGER_KIND) Node -> Special . Integer . IncrementerHook = (struct Hook *)TagItem -> ti_Data; break; case LA_Min: if(Type == INTEGER_KIND) Node -> Special . Integer . Min = TagItem -> ti_Data; #ifdef DO_FRACTION_KIND else { if(Type == FRACTION_KIND) Node -> Special . String . Min = TagItem -> ti_Data; } #endif break; case LA_Max: if(Type == INTEGER_KIND) Node -> Special . Integer . Max = TagItem -> ti_Data; #ifdef DO_FRACTION_KIND else { if(Type == FRACTION_KIND) Node -> Special . String . Max = TagItem -> ti_Data; } #endif break; case LABX_ReserveSpace: if(Type == BOX_KIND) Node -> Special . Box . ReserveSpace = TagItem -> ti_Data; break; case LA_Chars: Node -> Chars = TagItem -> ti_Data; break; case LA_LabelPlace: Node -> LabelPlace = TagItem -> ti_Data; if(Type == MX_KIND) { if(TagItem -> ti_Data == PLACE_RIGHT) Node -> LabelPlace = PLACE_RIGHT; else Node -> LabelPlace = PLACE_LEFT; } break; case LA_ExtraSpace: Node -> ExtraSpace = (WORD)TagItem -> ti_Data; if(Node -> ExtraSpace == 1) Node -> ExtraSpace = 3; break; case LA_Center: Node -> Centered = TagItem -> ti_Data; break; case LA_PageSelector: Node -> PageSelector = TagItem -> ti_Data; break; case LABT_ExtraFat: if(Node -> Type == BUTTON_KIND) Node -> Special . Button . ExtraFat = TagItem -> ti_Data; break; #ifdef DO_PICKSHORTCUTS case LA_NoKey: Node -> NoKey = TagItem -> ti_Data; break; #endif case LA_HighLabel: Node -> HighLabel = TagItem -> ti_Data; break; case LAPA_SmallPalette: if(Type == PALETTE_KIND) Node -> Special . Palette . SmallPalette = TagItem -> ti_Data; break; case LA_Lines: if(Type == BOX_KIND) { LONG Count = TagItem -> ti_Data; if(Node -> Lines != Count) { if(Node -> Special . Box . Lines) { LTK_Free(Handle,Node -> Special . Box . Lines,sizeof(STRPTR) * Node -> Lines); Node -> Special . Box . Lines = NULL; } } if(!Node -> Special . Box . Lines) { if(Node -> Special . Box . Lines = (STRPTR *)LTK_Alloc(Handle,sizeof(STRPTR) * Count)) { LONG i; for(i = 0 ; i < Count ; i++) Node -> Special . Box . Lines[i] = ""; } else Handle -> Failed = TRUE; } } Node -> Lines = TagItem -> ti_Data; break; case LA_Picker: if(Type == TEXT_KIND) Node -> Special . Text . UsePicker = TagItem -> ti_Data; if(Type == STRING_KIND) Node -> Special . String . UsePicker = TagItem -> ti_Data; break; case LAGR_Spread: if(Type == GROUP_KIND) Node -> Special . Group . Spread = TagItem -> ti_Data; break; case LAGR_SameSize: if(Type == GROUP_KIND) Node -> Special . Group . SameSize = TagItem -> ti_Data; break; case LAGR_LastAttributes: if(Type == GROUP_KIND) Node -> Special . Group . LastAttributes = TagItem -> ti_Data; break; case LAGR_ActivePage: if(Type == GROUP_KIND) { Node -> Special . Group . ActivePage = TagItem -> ti_Data; Node -> Special . Group . Paging = TRUE; } break; case LABT_ReturnKey: if(Type == BUTTON_KIND) Node -> Special . Button . ReturnKey = TagItem -> ti_Data; break; case LABT_EscKey: if(Type == BUTTON_KIND) Node -> Special . Button . EscKey = TagItem -> ti_Data; break; case LALV_CursorKey: if(Type == LISTVIEW_KIND) Node -> Special . List . CursorKey = TagItem -> ti_Data; break; case LALV_MaxGrowX: if(Type == LISTVIEW_KIND) { Handle -> GrowView = Node; Node -> Special . List . MaxGrowX = TagItem -> ti_Data; } break; case LALV_MaxGrowY: if(Type == LISTVIEW_KIND) { Handle -> GrowView = Node; Node -> Special . List . MaxGrowY = TagItem -> ti_Data; } break; case LALV_Labels: if(Type == LISTVIEW_KIND) { STRPTR *Labels = (STRPTR *)TagItem -> ti_Data; if(*Labels) { struct List *SomeList; if(SomeList = LTK_Alloc(Handle,sizeof(struct List))) { struct Node *SomeNode; NewList(SomeList); Node -> Special . List . Labels = SomeList; while(*Labels) { if(SomeNode = LTK_Alloc(Handle,sizeof(struct Node) + strlen(*Labels) + 1)) { SomeNode -> ln_Name = (STRPTR)(SomeNode + 1); strcpy(SomeNode -> ln_Name,*Labels++); AddTail(SomeList,SomeNode); } } } } } break; case LA_Link: if(Type == LISTVIEW_KIND) Node -> Special . List . LinkID = TagItem -> ti_Data; if(Type == STRING_KIND || Type == FRACTION_KIND) Node -> Special . String . LinkID = TagItem -> ti_Data; break; #ifdef DO_TAPEDECK_KIND case LATD_ButtonType: if(Type == TAPEDECK_KIND) Node -> Special . TapeDeck . ButtonType = TagItem -> ti_Data; break; case LATD_Toggle: if(Type == TAPEDECK_KIND) Node -> Special . TapeDeck . Toggle = TagItem -> ti_Data; break; case LATD_Pressed: if(Type == TAPEDECK_KIND) Node -> Current = TagItem -> ti_Data; break; case LATD_Smaller: if(Type == TAPEDECK_KIND) Node -> Special . TapeDeck . Smaller = TagItem -> ti_Data; break; #endif /* DO_TAPEDECK_KIND */ #ifdef DO_GAUGE_KIND case LAGA_Percent: if(Type == GAUGE_KIND) { LONG Percent = (LONG)TagItem -> ti_Data; if(Percent <= 0) Node -> Current = 0; else { if(Percent > 100) Node -> Current = 100; else Node -> Current = Percent; } } break; case LAGA_InfoLength: if(Type == GAUGE_KIND) { LONG Length = (LONG)TagItem -> ti_Data; if(Length > Node -> Special . Gauge . InfoLength) { STRPTR NewText; if(NewText = (STRPTR)AsmAllocPooled(Handle -> Pool,Length + 1,SysBase)) { if(Node -> Special . Gauge . InfoText) { strcpy(NewText,Node -> Special . Gauge . InfoText); AsmFreePooled(Handle -> Pool,Node -> Special . Gauge . InfoText,Node -> Special . Gauge . InfoLength + 1,SysBase); } NewText[0] = 0; Node -> Special . Gauge . InfoText = NewText; Node -> Special . Gauge . InfoLength = Length; } else Handle -> Failed = TRUE; } } break; case LAGA_InfoText: if(Type == GAUGE_KIND) { STRPTR SomeText = (STRPTR)TagItem -> ti_Data; LONG Len = strlen(SomeText); if(!Node -> Special . Gauge . InfoLength) { if(Node -> Special . Gauge . InfoText = (STRPTR)AsmAllocPooled(Handle -> Pool,Len + 1,SysBase)) Node -> Special . Gauge . InfoLength = Len; else Handle -> Failed = TRUE; } if(Node -> Special . Gauge . InfoLength) { if(Len > Node -> Special . Gauge . InfoLength) Len = Node -> Special . Gauge . InfoLength; CopyMem(SomeText,Node -> Special . Gauge . InfoText,Len); Node -> Special . Gauge . InfoText[Len] = 0; } } break; #endif case LALV_ExtraLabels: if(Type == LISTVIEW_KIND) Node -> Special . List . ExtraLabels = (STRPTR *)TagItem -> ti_Data; break; case LAFR_InnerWidth: if(Type == FRAME_KIND) Node -> Special . Frame . InnerWidth = TagItem -> ti_Data; break; case LAFR_InnerHeight: if(Type == FRAME_KIND) Node -> Special . Frame . InnerHeight = TagItem -> ti_Data; break; case LA_DrawBox: if(Type == FRAME_KIND) Node -> Special . Frame . DrawBox = TagItem -> ti_Data; if(Type == BOX_KIND) Node -> Special . Box . DrawBox = TagItem -> ti_Data; break; case LABX_AlignText: if(Type == BOX_KIND) Node -> Special . Box . AlignText = TagItem -> ti_Data; break; case LABX_Labels: if(Type == BOX_KIND) { STRPTR *Labels = (STRPTR *)TagItem -> ti_Data; LONG Count = 0; while(Labels[Count]) Count++; if(Node -> Lines != Count) { if(Node -> Special . Box . Lines) { LTK_Free(Handle,Node -> Special . Box . Lines,sizeof(STRPTR) * Node -> Lines); Node -> Special . Box . Lines = NULL; } } if(Count) { if(!Node -> Special . Box . Lines) { if(Node -> Special . Box . Lines = LTK_Alloc(Handle,sizeof(STRPTR) * Count)) { LONG i; for(i = 0 ; i < Count ; i++) Node -> Special . Box . Lines[i] = ""; } } } Node -> Lines = Count; Node -> Special . Box . Labels = Labels; } break; case LABX_Lines: if(Type == BOX_KIND) { STRPTR *Lines = (STRPTR *)TagItem -> ti_Data; LONG Count = 0; while(Lines[Count]) Count++; if(Node -> Lines && Count > Node -> Lines) Count = Node -> Lines; if(Count) { if(!Node -> Special . Box . Lines) Node -> Special . Box . Lines = LTK_Alloc(Handle,sizeof(STRPTR) * Count); if(Node -> Special . Box . Lines) { LONG i; for(i = 0 ; i < Count ; i++) Node -> Special . Box . Lines[i] = Lines[i]; } } Node -> Lines = Count; } break; case GA_Disabled: Node -> Disabled = TagItem -> ti_Data; break; case GTCB_Checked: if(Type == CHECKBOX_KIND) Node -> Current = TagItem -> ti_Data; break; case GTLV_Labels: if(Type == LISTVIEW_KIND) Node -> Special . List . Labels = (struct List *)TagItem -> ti_Data; break; case GTLV_ReadOnly: if(Type == LISTVIEW_KIND) Node -> Special . List . ReadOnly = TagItem -> ti_Data; break; case GTLV_MakeVisible: case GTLV_Selected: if(Type == LISTVIEW_KIND) Node -> Current = (LONG)TagItem -> ti_Data; break; case GTLV_CallBack: if(Type == LISTVIEW_KIND) Node -> Special . List . CallBack = (struct Hook *)TagItem -> ti_Data; break; case GTLV_MaxPen: if(Type == LISTVIEW_KIND) Node -> Special . List . MaxPen = TagItem -> ti_Data; break; case GTMX_Labels: if(Type == MX_KIND) Node -> Special . Radio . Choices = (STRPTR *)TagItem -> ti_Data; break; case GTMX_Active: if(Type == MX_KIND) Node -> Current = TagItem -> ti_Data; break; case GTMX_TitlePlace: if(Type == MX_KIND && Label) { if(TagItem -> ti_Data == PLACE_RIGHT) Node -> Special . Radio . TitlePlace = PLACETEXT_RIGHT; else Node -> Special . Radio . TitlePlace = PLACETEXT_LEFT; } break; case GTTX_Text: if(Type == TEXT_KIND) Node -> Special . Text . Text = (STRPTR)TagItem -> ti_Data; break; case GTTX_CopyText: if(Type == TEXT_KIND) Node -> Special . Text . CopyText = TagItem -> ti_Data; break; case GTTX_Border: if(Type == TEXT_KIND) Node -> Special . Text . Border = TagItem -> ti_Data; break; case GTNM_Number: if(Type == NUMBER_KIND) Node -> Special . Number . Number = TagItem -> ti_Data; break; case GTNM_Border: if(Type == NUMBER_KIND) Node -> Special . Number . Border = TagItem -> ti_Data; break; case GTTX_Justification: if(Type == NUMBER_KIND) Node -> Special . Number . Justification = TagItem -> ti_Data; if(Type == TEXT_KIND) Node -> Special . Text . Justification = TagItem -> ti_Data; break; case GTCY_Labels: if(Type == CYCLE_KIND) Node -> Special . Cycle . Choices = (STRPTR *)TagItem -> ti_Data; break; case GTCY_Active: if(Type == CYCLE_KIND) Node -> Current = TagItem -> ti_Data; break; case GTPA_Depth: if(Type == PALETTE_KIND) { Node -> Special . Palette . Depth = TagItem -> ti_Data; if(Handle -> MaxPen < (1L << Node -> Special . Palette . Depth) - 1) Handle -> MaxPen = (1L << Node -> Special . Palette . Depth) - 1; } break; case GTPA_Color: if(Type == PALETTE_KIND) Node -> Current = TagItem -> ti_Data; break; case GTPA_ColorOffset: if(Type == PALETTE_KIND) Node -> Min = TagItem -> ti_Data; break; case GTPA_NumColors: if(Type == PALETTE_KIND) { Node -> Special . Palette . NumColours = TagItem -> ti_Data; if(Node -> Special . Palette . ColourTable) { LONG i; for(i = 0 ; i < Node -> Special . Palette . NumColours ; i++) { if(Node -> Special . Palette . ColourTable[i] > Handle -> MaxPen) Handle -> MaxPen = Node -> Special . Palette . ColourTable[i]; } } } break; case GTPA_ColorTable: if(Type == PALETTE_KIND) { Node -> Special . Palette . ColourTable = (UBYTE *)TagItem -> ti_Data; if(Node -> Special . Palette . NumColours) { LONG i; for(i = 0 ; i < Node -> Special . Palette . NumColours ; i++) { if(Node -> Special . Palette . ColourTable[i] > Handle -> MaxPen) Handle -> MaxPen = Node -> Special . Palette . ColourTable[i]; } } } break; case GTSC_Top: if(Type == SCROLLER_KIND) Node -> Current = TagItem -> ti_Data; break; case GTSC_Total: if(Type == SCROLLER_KIND) Node -> Max = TagItem -> ti_Data; break; case GTSC_Visible: if(Type == SCROLLER_KIND) Node -> Special . Scroller . Visible = TagItem -> ti_Data; break; case GTSC_Arrows: if(Type == SCROLLER_KIND) Node -> Special . Scroller . Arrows = (TagItem -> ti_Data != 0); break; case LASC_Thin: if(Type == SCROLLER_KIND) Node -> Special . Scroller . Thin = TagItem -> ti_Data; break; case PGA_Freedom: if(Type == SCROLLER_KIND) Node -> Special . Scroller . Vertical = (TagItem -> ti_Data == LORIENT_VERT); break; case GTSL_Min: if(Type == SLIDER_KIND) Node -> Min = TagItem -> ti_Data; break; case GTSL_Max: if(Type == SLIDER_KIND) Node -> Max = TagItem -> ti_Data; break; case GTSL_Level: if(Type == SLIDER_KIND) Node -> Current = TagItem -> ti_Data; break; case GTSL_LevelFormat: if(Type == SLIDER_KIND) Node -> Special . Slider . LevelFormat = (STRPTR)TagItem -> ti_Data; break; case GTSL_LevelPlace: if(Type == SLIDER_KIND) { if(TagItem -> ti_Data == PLACE_RIGHT) Node -> Special . Slider . LevelPlace = PLACETEXT_RIGHT; else Node -> Special . Slider . LevelPlace = PLACETEXT_LEFT; } break; case GTSL_DispFunc: if(Type == SLIDER_KIND) { APTR p = (APTR)TagItem -> ti_Data; Node -> Special . Slider . DispFunc = (DISPFUNC)p; } break; case LASL_FullCheck: if(Type == SLIDER_KIND) Node -> Special . Slider . FullLevelCheck = TagItem -> ti_Data; break; case GTST_String: if(Type == STRING_KIND || Type == PASSWORD_KIND) Node -> Special . String . String = (STRPTR)TagItem -> ti_Data; break; case GTST_MaxChars: if(Type == STRING_KIND || Type == PASSWORD_KIND) Node -> Special . String . MaxChars = TagItem -> ti_Data; break; case GTST_EditHook: if(Type == STRING_KIND) Node -> Special . String . EditHook = (struct Hook *)TagItem -> ti_Data; else { if(Type == INTEGER_KIND) Node -> Special . Integer . EditHook = (struct Hook *)TagItem -> ti_Data; } break; case STRINGA_Justification: if(Type == STRING_KIND || Type == FRACTION_KIND || Type == PASSWORD_KIND) Node -> Special . String . Justification = TagItem -> ti_Data; else { if(Type == INTEGER_KIND) Node -> Special . Integer . Justification = TagItem -> ti_Data; } break; #ifdef DO_FRACTION_KIND case LAFC_MaxChars: if(Type == FRACTION_KIND) Node -> Special . String . MaxChars = TagItem -> ti_Data; break; case LAFC_Number: if(Type == FRACTION_KIND) Node -> Current = TagItem -> ti_Data; break; #endif case LAIN_UseIncrementers: if(Type == INTEGER_KIND) { if(Node -> Special . Integer . UseIncrementers = TagItem -> ti_Data) Handle -> IDCMP |= IDCMP_INTUITICKS; } break; case GTIN_Number: if(Type == INTEGER_KIND) Node -> Special . Integer . Number = TagItem -> ti_Data; break; case GTIN_MaxChars: if(Type == INTEGER_KIND) Node -> Special . Integer . MaxChars = TagItem -> ti_Data; break; } } } if(Handle -> Failed) return; if((Type == FRACTION_KIND || Type == STRING_KIND || Type == INTEGER_KIND) && Node -> Special . String . MaxHistoryLines) { if(!Node -> Special . Integer . HistoryHook) { struct Hook *Hook; if(Hook = (struct Hook *)LTK_Alloc(Handle,sizeof(struct Hook) + sizeof(struct MinList))) { struct MinList *List; List = Hook -> h_Data = (APTR)(Hook + 1); NewList((struct List *)List); Hook -> h_Entry = (HOOKFUNC)LTK_DefaultHistoryHook; Node -> Special . Integer . HistoryHook = Hook; } } if(Node -> Special . Integer . HistoryHook) { struct Node *TextNode; struct MinList *List = (struct List *)Node -> Special . Integer . HistoryHook -> h_Data; Node -> Special . Integer . LayoutHandle = Handle; Node -> Special . Integer . NumHistoryLines = 0; TextNode = (struct Node *)List -> mlh_Head; while(TextNode -> ln_Succ) { Node -> Special . Integer . NumHistoryLines++; TextNode = TextNode -> ln_Succ; } } } if(Type == TEXT_KIND && Node -> Special . Text . CopyText && Node -> Special . Text . Text) { LONG len; STRPTR text; len = strlen(Node -> Special . Text . Text); if(text = LTK_Alloc(Handle,len + 1)) { strcpy(text,Node -> Special . Text . Text); Node -> Special . Text . Text = text; } } if(FirstLabel != -1 && LastLabel != -1) { if(Type == MX_KIND || Type == CYCLE_KIND || Type == LISTVIEW_KIND || Type == BOX_KIND) { if(!Handle -> LocaleHook) Handle -> Failed = TRUE; else { if(Type == LISTVIEW_KIND) { struct List *SomeList; if(SomeList = (struct List *)LTK_Alloc(Handle,sizeof(struct List))) { struct Node *SomeNode; LONG Count = (LastLabel - FirstLabel + 1),i; NewList(SomeList); Node -> Special . List . Labels = SomeList; for(i = 0 ; i < Count ; i++) { if(SomeNode = LTK_Alloc(Handle,sizeof(struct Node))) { SomeNode -> ln_Name = (STRPTR)CallHookPkt(Handle -> LocaleHook,Handle,(APTR)(FirstLabel + i)); AddTail(SomeList,SomeNode); } } } } else { STRPTR *Labels; LONG Count = (LastLabel - FirstLabel + 1),i; if(Labels = LTK_Alloc(Handle,sizeof(STRPTR) * (Count + 1))) { for(i = 0 ; i < Count ; i++) Labels[i] = (STRPTR)CallHookPkt(Handle -> LocaleHook,Handle,(APTR)(FirstLabel + i)); Labels[i] = NULL; if(Type == MX_KIND) Node -> Special . Radio . Choices = Labels; else { if(Type == CYCLE_KIND) Node -> Special . Cycle . Choices = Labels; else { if(Type == BOX_KIND) { if(!Node -> Special . Box . Lines) { if(Node -> Special . Box . Lines = LTK_Alloc(Handle,sizeof(STRPTR) * Count)) { LONG i; for(i = 0 ; i < Count ; i++) Node -> Special . Box . Lines[i] = ""; } } Node -> Lines = Count; Node -> Special . Box . Labels = Labels; } } } } } } } } if(Type == BOX_KIND && Node -> Special . Box . ReserveSpace) { LONG Size; STRPTR Buffer; if(!Node -> Special . Box . Lines) { if(Node -> Special . Box . Lines = LTK_Alloc(Handle,sizeof(STRPTR) * Node -> Lines)) { LONG i; for(i = 0 ; i < Node -> Lines ; i++) Node -> Special . Box . Lines[i] = ""; } } if(!Node -> Chars) Size = 10; else Size = Node -> Chars; Node -> Special . Box . MaxSize = Size; if(Buffer = (STRPTR)LTK_Alloc(Handle,(Size + 1) * Node -> Lines)) { LONG i,Len; for(i = 0 ; i < Node -> Lines ; i++) { if(Node -> Special . Box . Lines[i]) { Len = strlen(Node -> Special . Box . Lines[i]); if(Len > Size) Len = Size; CopyMem(Node -> Special . Box . Lines[i],Buffer,Len); Buffer[Len] = 0; } else Buffer[0] = 0; Node -> Special . Box . Lines[i] = Buffer; Buffer += Size + 1; } } } if(Handle -> Failed) return; if(ParentList) { #ifdef DO_PASSWORD_KIND if(Type == PASSWORD_KIND) { STRPTR Buffer; if(!(Buffer = LTK_Alloc(Handle,2 * (Node -> Special . String . MaxChars + 1)))) return; Node -> Special . String . RealString = Buffer; Node -> Special . String . Original = Buffer + Node -> Special . String . MaxChars + 1; if(Node -> Special . String . String) { strcpy(Node -> Special . String . RealString, Node -> Special . String . String); strcpy(Node -> Special . String . Original, Node -> Special . String . String); } } #endif AddTail((struct List *)ParentList,(struct Node *)Node); if(Type == XBAR_KIND || Type == YBAR_KIND) Node -> Special . Bar . Parent = Handle -> CurrentGroup; } } } } /*****************************************************************************/ VOID __stdargs LT_AddL(LayoutHandle *handle,UBYTE type,ULONG labelID,LONG id,...) { if(handle) { struct TagItem *tagList; va_list varArg; va_start(varArg,id); tagList = (struct TagItem *)varArg; if(handle -> LocaleHook) { STRPTR label; label = (STRPTR)CallHookPkt(handle -> LocaleHook,handle,(APTR)labelID); LT_AddA(handle,type,label,id,tagList); } else handle -> Failed = TRUE; va_end(varArgs); } } /*****************************************************************************/ VOID __stdargs LT_New(LayoutHandle *handle,...) { va_list VarArgs; va_start(VarArgs,handle); LT_NewA(handle,(struct TagItem *)VarArgs); va_end(VarArgs); } VOID LIBENT LT_NewA(REG(a0) LayoutHandle *handle,REG(a1) struct TagItem *tagList) { if(handle) { struct TagItem *tag; UBYTE type; STRPTR label; ULONG id; if(tag = FindTagItem(LA_Type,tagList)) { type = tag -> ti_Data; if(type == END_KIND) { handle -> CurrentGroup = handle -> CurrentGroup -> Special . Group . ParentGroup; return; } if(tag = FindTagItem(LA_ID,tagList)) id = tag -> ti_Data; /* else*/ /* id = handle -> MaxID;*/ if(tag = FindTagItem(LA_LabelID,tagList)) { if(handle -> LocaleHook) label = (STRPTR)CallHookPkt(handle -> LocaleHook,handle,(APTR)tag -> ti_Data); else handle -> Failed = TRUE; } else label = (STRPTR)GetTagData(LA_LabelText,NULL,tagList); LT_AddA(handle,type,label,id,tagList); } else handle -> Failed = TRUE; } } /*****************************************************************************/ VOID LIBENT LT_EndGroup(REG(a0) LayoutHandle *handle) { LT_AddA(handle,END_KIND,NULL,0,NULL); } /*****************************************************************************/ struct Window * __stdargs LT_Layout(LayoutHandle *handle, STRPTR title,struct IBox *bounds,LONG extraWidth, LONG extraHeight,ULONG IDCMP, UBYTE align, ...) { struct Window *Result; va_list VarArgs; va_start(VarArgs,align); Result = LT_LayoutA(handle,title,bounds,extraWidth,extraHeight,IDCMP,align,(struct TagItem *)VarArgs); va_end(VarArgs); return(Result); } struct Window * LIBENT LT_LayoutA(REG(a0) LayoutHandle *handle, REG(a1) STRPTR title,REG(a2) struct IBox *bounds,REG(d0) LONG extraWidth, REG(d1) LONG extraHeight,REG(d2) ULONG IDCMP, REG(d3) UBYTE align, REG(a3) struct TagItem *TagParams) { LONG left, top, width, height; struct IBox newBounds; struct Menu *menu; struct TagItem *item; LONG placeLeft; LONG placeTop; struct IBox zoomBox; struct IBox *zoom; LONG i; struct TextFont *font; struct TagItem *NewTags = NULL,*Tags; BOOLEAN FillBack = FALSE,BlockParent = handle -> BlockParent; struct Window *Parent = handle -> Parent; if(!handle) return(NULL); if(!bounds) { LTK_GetDisplayClip(handle -> Screen,&newBounds . Left,&newBounds . Top,&newBounds . Width,&newBounds . Height); bounds = &newBounds; } if(title) top = handle -> Screen -> WBorTop + handle -> Screen -> Font -> ta_YSize + 1 + handle -> InterHeight; else top = handle -> Screen -> WBorTop + handle -> InterHeight; left = handle -> Screen -> WBorLeft + handle -> InterWidth; LTK_CreateGadgets(handle,bounds,left,top,left + handle -> InterWidth + handle -> Screen -> WBorRight,top + handle -> InterHeight + handle -> Screen -> WBorBottom); if(handle -> Failed) return(NULL); width = left + handle -> TopGroup -> Width + handle -> InterWidth + handle -> Screen -> WBorRight; height = top + handle -> TopGroup -> Height + handle -> InterHeight + handle -> Screen -> WBorBottom; if(align & ALIGNF_LEFT) placeLeft = 0; else { if(align & ALIGNF_RIGHT) placeLeft = bounds -> Width - (width + extraWidth); else placeLeft = (bounds -> Width - (width + extraWidth)) / 2; } if(align & ALIGNF_TOP) placeTop = 0; else { if(align & ALIGNF_BOTTOM) placeTop = bounds -> Height - (height + extraHeight); else placeTop = (bounds -> Height - (height + extraHeight)) / 2; } if(align & ALIGNF_EXTRA_LEFT) placeLeft += extraWidth; else { if(!(align & ALIGNF_EXTRA_RIGHT)) placeLeft += extraWidth / 2; } if(align & ALIGNF_EXTRA_TOP) placeTop += extraHeight; else { if(!(align & ALIGNF_EXTRA_BOTTOM)) placeTop += extraHeight / 2; } placeLeft += bounds -> Left; placeTop += bounds -> Top; if(placeLeft < 0) placeLeft = 0; if(placeTop < 0) placeTop = 0; menu = NULL; zoom = NULL; handle -> AutoRefresh = TRUE; #ifdef DO_CLONING if(handle -> CloneExtra) { placeLeft = 0; placeTop = handle -> CloneExtra -> Screen -> BarHeight + 1; zoomBox . Left = placeLeft; zoomBox . Top = placeTop; } #endif /* DO_CLONING */ /* ALWAYS */ { struct TagItem *TagList = (struct TagItem *)TagParams; while(item = NextTagItem(&TagList)) { switch((ULONG)item -> ti_Tag) { case LA_Menu: handle -> IDCMP |= IDCMP_MENUPICK; menu = (struct Menu *)item -> ti_Data; break; case LAWN_UserPort: handle -> MsgPort = (struct MsgPort *)item -> ti_Data; break; case LAWN_HelpHook: handle -> HelpHook = (struct Hook *)item -> ti_Data; break; case LAWN_Left: placeLeft = item -> ti_Data; break; case LAWN_Top: placeTop = item -> ti_Data; break; case LAWN_Parent: Parent = (struct Window *)item -> ti_Data; break; case LAWN_BlockParent: BlockParent = item -> ti_Data; break; case LAWN_BelowMouse: if((placeLeft = handle -> Screen -> MouseX - (width / 2)) < 0) placeLeft = 0; if((placeTop = handle -> Screen -> MouseY - (height / 2)) < 0) placeTop = 0; break; case LAWN_Zoom: if(item -> ti_Data) { if(V39) { zoomBox . Left = -1; zoomBox . Top = -1; } else { zoomBox . Left = placeLeft; zoomBox . Top = placeTop; } zoomBox . Width = width; zoomBox . Height = handle -> Screen -> WBorTop + handle -> Screen -> Font -> ta_YSize + 1; zoom = &zoomBox; } break; case LAWN_MaxPen: handle -> MaxPen = (LONG)item -> ti_Data; break; case LAWN_MoveToWindow: handle -> MoveToWindow = (LONG)item -> ti_Data; break; case LAWN_AutoRefresh: handle -> AutoRefresh = (LONG)item -> ti_Data; break; } } } Tags = (struct TagItem *)TagParams; if(handle -> BackgroundPen && !V39) { if(NewTags = CloneTagItems(Tags)) { STATIC Tag Filter[] = { WA_SimpleRefresh,TAG_DONE }; FilterTagItems(NewTags,Filter,TAGFILTER_NOT); Tags = NewTags; FillBack = TRUE; } else return(NULL); } if(Parent) { WORD Left,Top,Width,Height,MoveLeft,MoveTop, WindowLeft,WindowTop,WindowWidth,WindowHeight; WindowLeft = Parent -> LeftEdge + Parent -> BorderLeft; WindowTop = Parent -> TopEdge + Parent -> BorderTop; WindowWidth = Parent -> Width - (Parent -> BorderLeft + Parent -> BorderRight); WindowHeight = Parent -> Height - (Parent ->BorderTop + Parent -> BorderBottom); LTK_GetDisplayClip(Parent -> WScreen,&Left,&Top,&Width,&Height); if((MoveLeft = WindowLeft + (WindowWidth - width) / 2) < 0) MoveLeft = 0; if((MoveTop = WindowTop + (WindowHeight - height) / 2) < 0) MoveTop = 0; if(MoveLeft < Left || MoveLeft + width > Left + Width) MoveLeft = -1; if(MoveTop < Top || MoveTop + height > Top + Height) MoveTop = -1; if(MoveTop != -1 && MoveLeft != -1) { placeLeft = MoveLeft; placeTop = MoveTop; } } if(BlockParent && Parent) { LT_LockWindow(Parent); handle -> Parent = Parent; } if(handle -> Window = OpenWindowTags(NULL, WA_Left, placeLeft, WA_Top, placeTop, WA_Width, width, WA_Height, height, WA_NewLookMenus, TRUE, WA_CustomScreen, handle -> Screen, WA_BackFill, &handle -> BackfillHook, !FillBack ? WA_Gadgets : TAG_IGNORE, handle -> List, zoom ? WA_Zoom : TAG_IGNORE, zoom, !handle -> MsgPort ? WA_IDCMP : TAG_IGNORE, IDCMP_REFRESHWINDOW | IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP | handle -> IDCMP, title ? WA_Title : TAG_IGNORE, title, handle -> AmigaGlyph ? WA_AmigaKey : TAG_IGNORE, handle -> AmigaGlyph, handle -> CheckGlyph ? WA_Checkmark : TAG_IGNORE, handle -> CheckGlyph, TAG_MORE,Tags)) { font = handle -> RPort . Font; handle -> RPort = *handle -> Window -> RPort; LTK_SetFont(handle,font); if(NewTags) { FreeTagItems(NewTags); NewTags = NULL; } if(V39) { if(handle -> MaxPen > 0) { SetMaxPen(&handle -> RPort,handle -> MaxPen); SetMaxPen(handle -> Window -> RPort,handle -> MaxPen); } } if(FillBack) { LTK_SetAPen(handle -> Window -> RPort,handle -> BackgroundPen); RectFill(handle -> Window -> RPort,handle -> Window -> BorderLeft,handle -> Window -> BorderTop,handle -> Window -> Width - (handle -> Window -> BorderRight + 1),handle -> Window -> Height - (handle -> Window -> BorderBottom + 1)); AddGList(handle -> Window,handle -> List,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(handle -> List,handle -> Window,NULL,(UWORD)-1); } GT_RefreshWindow(handle -> Window,NULL); LTK_DrawGroup(handle,handle -> TopGroup); LTK_MoveToWindow(handle); if(handle -> MsgPort) { handle -> Window -> UserPort = handle -> MsgPort; if(!ModifyIDCMP(handle -> Window,IDCMP_REFRESHWINDOW | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP | handle -> IDCMP)) { handle -> Window -> UserPort = NULL; return (NULL); } } if(menu) SetMenuStrip(handle -> Window,menu); handle -> Previous = NULL; for(i = 0 ; i < handle -> Count ; i++) { if(handle -> GadgetArray[i]) { ObjectNode *node; if(GETOBJECT(handle -> GadgetArray[i],node)) { if(LIKE_STRING_KIND(node) || (node -> Type == INTEGER_KIND)) { if(!handle -> Previous) handle -> Previous = handle -> GadgetArray[i]; } } } } #ifdef DO_CLONING if(handle -> CloneExtra) ScreenToFront(handle -> Window -> WScreen); #endif } else { if(handle -> Parent) { LT_UnlockWindow(handle -> Parent); handle -> Parent = NULL; } } FreeTagItems(NewTags); return(handle -> Window); } /*****************************************************************************/ struct Menu * __stdargs LT_LayoutMenus(LayoutHandle *handle,struct NewMenu *menuTemplate,...) { struct Menu *Result; va_list VarArgs; va_start(VarArgs,menuTemplate); Result = LT_LayoutMenusA(handle,menuTemplate,(struct TagItem *)VarArgs); va_end(VarArgs); return(Result); } struct Menu * LIBENT LT_LayoutMenusA(REG(a0) LayoutHandle *handle,REG(a1) struct NewMenu *menuTemplate,REG(a2) struct TagItem *TagParams) { struct Menu *menu; menu = NULL; if(handle) { struct TagItem *tag; LONG label; BOOLEAN foundFirst; BOOLEAN foundLast; foundFirst = FALSE; foundLast = FALSE; if(tag = FindTagItem(LA_FirstLabel,(struct TagItem *)TagParams)) { foundFirst = TRUE; label = tag -> ti_Data; } if(tag = FindTagItem(LA_LastLabel,(struct TagItem *)TagParams)) foundLast = TRUE; if(foundFirst == foundLast) { struct NewMenu *localTemplate; localTemplate = NULL; if(foundFirst) { if(handle -> LocaleHook) { LONG count; count = 0; while(menuTemplate[count] . nm_Type != NM_END) count++; count++; if(localTemplate = AllocVec(sizeof(struct NewMenu) * count,MEMF_ANY | MEMF_PUBLIC)) { LONG i; CopyMem(menuTemplate,localTemplate,sizeof(struct NewMenu) * count); for(i = 0 ; i < count ; i++) { if(localTemplate[i] . nm_Label != NM_BARLABEL && (localTemplate[i] . nm_Type == NM_TITLE || localTemplate[i] . nm_Type == NM_ITEM || localTemplate[i] . nm_Type == NM_SUB)) { localTemplate[i] . nm_Label = (STRPTR)CallHookPkt(handle -> LocaleHook,handle,(APTR)label); label++; } } } } menuTemplate = localTemplate; } if(menuTemplate) { if(menu = CreateMenusA(menuTemplate,NULL)) { if(!LayoutMenus(menu,handle -> VisualInfo, GTMN_NewLookMenus, TRUE, handle -> AmigaGlyph ? GTMN_AmigaKey : TAG_IGNORE,handle -> AmigaGlyph, handle -> CheckGlyph ? GTMN_Checkmark : TAG_IGNORE,handle -> CheckGlyph, TAG_DONE)) { FreeMenus(menu); menu = NULL; } } if(localTemplate) FreeVec(localTemplate); } } } return(menu); } /*****************************************************************************/ #ifdef DO_FRACTION_KIND VOID LIBENT LT_Fixed2String(REG(d0) FIXED fixed,REG(d1) STRPTR buffer) { sprintf(buffer,"%ld%lc%ld",fixed / FIXED_UNITY,LTK_Locale ? LTK_Locale -> loc_DecimalPoint[0] : ' . ',fixed % FIXED_UNITY); } #endif /*****************************************************************************/ #ifdef DO_FRACTION_KIND FIXED LIBENT LT_String2Fixed(REG(a0) STRPTR buffer) { UBYTE localBuffer[20]; UBYTE decimalPoint; LONG i,left,right; if(LTK_Locale) decimalPoint = LTK_Locale -> loc_DecimalPoint[0]; else decimalPoint = '.'; strcpy(localBuffer,buffer); i = 0; while(buffer[i]) { if(localBuffer[i] == decimalPoint) { localBuffer[i] = 0; if(i) left = Atol(localBuffer); else left = 0; if(localBuffer[i + 1]) { UBYTE rest[4]; CopyMem(&localBuffer[i + 1],rest,3); rest[3] = 0; right = Atol(rest); } else right = 0; return((FIXED)(left * FIXED_UNITY + right)); } i++; } left = Atol(localBuffer); return((FIXED)(left * FIXED_UNITY)); } #endif /*****************************************************************************/ #ifdef DO_FRACTION_KIND ULONG LIBENT LT_FixedMult(REG(d0) FIXED fixed,REG(d1) ULONG factor) { return((fixed * factor) / FIXED_UNITY); } #endif /*****************************************************************************/ BOOL LT_Init() { if(SysBase) return(TRUE); else { SysBase = *(struct ExecBase **)4; if(SysBase -> LibNode . lib_Version < 37) { SysBase = NULL; return(FALSE); } else { V39 = (SysBase -> LibNode . lib_Version >= 39); V40 = (SysBase -> LibNode . lib_Version >= 40); IntuitionBase = OpenLibrary("intuition.library",37); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37); UtilityBase = OpenLibrary("utility.library",37); GadToolsBase = OpenLibrary("gadtools.library",37); KeymapBase = OpenLibrary("keymap.library",37); if(LocaleBase = OpenLibrary("locale.library",38)) LTK_Locale = OpenLocale(NULL); if(IntuitionBase && GfxBase && UtilityBase && GadToolsBase && KeymapBase) { if(LTK_ImageClass = MakeClass(NULL,IMAGECLASS,NULL,sizeof(ImageInfo),0)) { #ifdef DO_PICKSHORTCUTS InitSemaphore(<K_KeySemaphore); #endif /* DO_PICKSHORTCUTS */ LTK_ImageClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)LTK_ImageDispatch; InitSemaphore(<K_LockSemaphore); NewList(<K_LockList); return(TRUE); } } LT_Exit(); return(FALSE); } } } /*****************************************************************************/ VOID LT_Exit() { if(SysBase) { if(LTK_ImageClass) { FreeClass(LTK_ImageClass); LTK_ImageClass = NULL; } if(LTK_Locale) { CloseLocale(LTK_Locale); LTK_Locale = NULL; } CloseLibrary(LocaleBase); LocaleBase = NULL; CloseLibrary(KeymapBase); KeymapBase = NULL; CloseLibrary(GadToolsBase); GadToolsBase = NULL; CloseLibrary(UtilityBase); UtilityBase = NULL; CloseLibrary(GfxBase); GfxBase = NULL; CloseLibrary(IntuitionBase); IntuitionBase = NULL; SysBase = NULL; } } /*****************************************************************************/ LONG LIBENT LT_LabelWidth(REG(a0) LayoutHandle *handle,REG(a1) STRPTR label) { if(handle) { LONG len; LONG cnt; cnt = 0; len = 0; while(label[len]) { if(label[len] == '_') cnt += TextLength(&handle -> RPort,"_",1); len++; } return(TextLength(&handle -> RPort,label,len) - cnt); } else return(0); } /*****************************************************************************/ LONG LIBENT LT_LabelChars(REG(a0) LayoutHandle *handle,REG(a1) STRPTR label) { if(handle) return((LT_LabelWidth(handle,label) + handle -> GlyphWidth - 1) / handle -> GlyphWidth); else return(0); } /****************************************************************************/ VOID LIBENT LT_LockWindow(REG(a0) struct Window *window) { if(window) { LockNode *lockNode; BOOLEAN found; found = FALSE; ObtainSemaphore(<K_LockSemaphore); SCANLIST(<K_LockList,lockNode) { if(lockNode -> Window == window) { lockNode -> Count++; found = TRUE; break; } } if(!found) { if(lockNode = AllocMem(sizeof(LockNode),MEMF_PUBLIC | MEMF_ANY | MEMF_CLEAR)) { AddTail((struct List *)<K_LockList,(struct Node *)lockNode); lockNode -> Window = window; lockNode -> OldIDCMPFlags = window -> IDCMPFlags; lockNode -> Count = 1; lockNode -> MinWidth = window -> MinWidth; lockNode -> MaxWidth = window -> MaxWidth; lockNode -> MinHeight = window -> MinHeight; lockNode -> MaxHeight = window -> MaxHeight; WindowLimits(window,window -> Width,window -> Height,window -> Width,window -> Height); ModifyIDCMP(window,window -> IDCMPFlags | IDCMP_SIZEVERIFY); if(V39) { SetWindowPointer(window, WA_BusyPointer, TRUE, WA_PointerDelay, TRUE, TAG_DONE); } else { STATIC UWORD __chip Stopwatch[(2 + 16) * 2] = { 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 }; SetPointer(window,Stopwatch,16,16,-6,0); } Request(&lockNode -> Requester,window); } } ReleaseSemaphore(<K_LockSemaphore); } } /****************************************************************************/ VOID LIBENT LT_UnlockWindow(REG(a0) struct Window *window) { if(window) { LockNode *lockNode; ObtainSemaphore(<K_LockSemaphore); SCANLIST(<K_LockList,lockNode) { if(lockNode -> Window == window) { if(--lockNode -> Count < 1) { Remove((struct Node *)lockNode); WindowLimits(window,lockNode -> MinWidth,lockNode -> MinHeight,lockNode -> MaxWidth,lockNode -> MaxHeight); EndRequest(&lockNode -> Requester,window); if(V39) SetWindowPointerA(window,NULL); else ClearPointer(window); ModifyIDCMP(window,lockNode -> OldIDCMPFlags); FreeMem(lockNode,sizeof(LockNode)); } break; } } ReleaseSemaphore(<K_LockSemaphore); } } /*****************************************************************************/ VOID LIBENT LT_DeleteWindowLock(REG(a0) struct Window *window) { if(window) { LockNode *lockNode; ObtainSemaphore(<K_LockSemaphore); SCANLIST(<K_LockList,lockNode) { if(lockNode -> Window == window) { Remove((struct Node *)lockNode); EndRequest(&lockNode -> Requester,window); if(V39) SetWindowPointerA(window,NULL); else ClearPointer(window); ModifyIDCMP(window,lockNode -> OldIDCMPFlags); FreeMem(lockNode,sizeof(LockNode)); break; } } ReleaseSemaphore(<K_LockSemaphore); } } /****************************************************************************/ VOID LIBENT LT_ShowWindow(REG(a0) LayoutHandle *handle,REG(a1) BOOL activate) { if(handle) { struct Window *window; window = handle -> Window; WindowToFront(window); if(activate) ActivateWindow(window); ScreenToFront(window -> WScreen); if((handle -> Window -> Flags & (WFLG_HASZOOM | WFLG_ZOOMED)) == (WFLG_HASZOOM | WFLG_ZOOMED)) { WORD i; ZipWindow(window); // wait for the window to unzoom before calling LTK_MoveToWindow() for(i = 0 ; i < 300 ; i++) { if(!handle -> Window -> Flags & WFLG_ZOOMED) break; WaitTOF(); } } LTK_MoveToWindow(handle); } } /****************************************************************************/ VOID LIBENT LT_Activate(REG(a0) LayoutHandle *handle,REG(d0) LONG id) { struct Gadget *gadget; if(gadget = LTK_FindGadget(handle,id)) { ObjectNode *node; if(GETOBJECT(gadget,node)) { if(!node -> Disabled) { if(LIKE_STRING_KIND(node) || (node -> Type == INTEGER_KIND)) { handle -> Previous = gadget; ActivateGadget(handle -> Previous,handle -> Window,NULL); } } } } } /****************************************************************************/ VOID LIBENT LT_PressButton(REG(a0) LayoutHandle *handle,REG(d0) LONG id) { struct Gadget *gadget; if(gadget = LTK_FindGadget(handle,id)) { ObjectNode *node; if(GETOBJECT(gadget,node)) { if(!node -> Disabled) LTK_BlinkButton(handle,gadget); } } } /****************************************************************************/ WORD LIBENT LT_GetCode(REG(d0) ULONG MsgQualifier,REG(d1) ULONG MsgClass,REG(d2) UWORD MsgCode,REG(a0) struct Gadget *MsgGadget) { if(MsgClass == IDCMP_RAWKEY && !(MsgCode & IECODE_UP_PREFIX) && KeymapBase) { UBYTE Buffer[10]; struct InputEvent Event; LONG Len; Event . ie_NextEvent = NULL; Event . ie_Code = MsgCode & ~IECODE_UP_PREFIX; Event . ie_Qualifier = MsgQualifier; Event . ie_Class = IECLASS_RAWKEY; Event . ie_SubClass = 0; Event . ie_position . ie_addr = (APTR)MsgGadget; Buffer[0] = 0; if((Len = MapRawKey(&Event,Buffer,9,NULL)) > 0) { if(Buffer[0] != 0x9B || Len == 1) return((WORD)Buffer[0]); } } return(-1); } /****************************************************************************/ #define MESSAGE_COOKIE 0x47138AEB struct IntuiMessage * LIBENT LT_GetIMsg(REG(a0) struct LayoutHandle *Handle) { if(Handle) { struct IntuiMessage *Msg = GT_GetIMsg(Handle -> Window -> UserPort); if(Msg) { struct IntuiMessage *Clone; if(Clone = (struct IntuiMessage *)AllocMem(sizeof(struct ExtIntuiMessage),MEMF_ANY)) { CopyMem(Msg,Clone,sizeof(struct ExtIntuiMessage)); Clone -> ExecMessage . mn_Node . ln_Name = (char *)MESSAGE_COOKIE; Clone -> ExecMessage . mn_Node . ln_Pri = -114; Clone -> ExecMessage . mn_ReplyPort = (struct MsgPort *)Clone; Clone -> SpecialLink = (struct IntuiMessage *)Clone; GT_ReplyIMsg(Msg); LT_HandleInput(Handle,Clone -> Qualifier,&Clone -> Class,&Clone -> Code,(struct Gadget **)&Clone -> IAddress); return(Clone); } else GT_ReplyIMsg(Msg); } } return(NULL); } VOID LIBENT LT_ReplyIMsg(REG(a0) struct IntuiMessage *Msg) { if(Msg) { if(Msg -> SpecialLink == (struct IntuiMessage *)Msg && Msg -> ExecMessage . mn_Node . ln_Name == (char *)MESSAGE_COOKIE && Msg -> ExecMessage . mn_Node . ln_Pri == -114 && Msg -> ExecMessage . mn_ReplyPort == (struct MsgPort *)Msg) FreeMem(Msg,sizeof(struct ExtIntuiMessage)); else GT_ReplyIMsg(Msg); } }