{ Copyright (c) 2022 by Free Pascal development team GEM interface unit for Atari TOS See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} { This is used for Pure-Pascal compatibility. For newly written code, consider using the aes/vdi units instead. } {$MODE FPC} {$MODESWITCH OUT+} {$PACKRECORDS 2} {$IFNDEF FPC_DOTTEDUNITS} unit gem; {$ENDIF FPC_DOTTEDUNITS} interface {$IFDEF FPC_DOTTEDUNITS} uses AtariApi.Aes, AtariApi.Vdi, AtariApi.Gemcmmn; {$ELSE FPC_DOTTEDUNITS} uses aes, vdi, gemcmmn; {$ENDIF FPC_DOTTEDUNITS} const LWhite = DWHITE; LBlack = DBLACK; LRed = DRED; LGreen = DGREEN; LBlue = DBLUE; LCyan = DCYAN; LYellow = DYELLOW; LMagenta = DMAGENTA; const BackSpace = $0E08; Tab = $0F09; S_Delete = $537F; S_Insert = $5200; Shift_Ins = $5230; Return = $1C0D; Enter = $720D; Undo = $6100; Help = $6200; Home = $4700; Cur_Up = $4800; Cur_Down = $5000; Cur_Left = $4B00; Cur_Right = $4D00; Shift_Home = $4737; Shift_CU = $4838; Shift_CD = $5032; Shift_CL = $4B34; Shift_CR = $4D36; Esc = $011B; Ctrl_A = $1E01; Ctrl_B = $3002; Ctrl_C = $2E03; Ctrl_D = $2004; Ctrl_E = $1205; Ctrl_F = $2106; Ctrl_G = $2207; Ctrl_H = $2308; Ctrl_I = $1709; Ctrl_J = $240A; Ctrl_K = $250B; Ctrl_L = $260C; Ctrl_M = $320D; Ctrl_N = $310E; Ctrl_O = $180F; Ctrl_P = $1910; Ctrl_Q = $1011; Ctrl_R = $1312; Ctrl_S = $1F13; Ctrl_T = $1414; Ctrl_U = $1615; Ctrl_V = $2F16; Ctrl_W = $1117; Ctrl_X = $2D18; Ctrl_Y = $2C19; Ctrl_Z = $151A; Ctrl_1 = $0211; Ctrl_2 = $0300; Ctrl_3 = $0413; Ctrl_4 = $0514; Ctrl_5 = $0615; Ctrl_6 = $071E; Ctrl_7 = $0817; Ctrl_8 = $0918; Ctrl_9 = $0A19; Ctrl_0 = $0B10; Alt_A = $1E00; Alt_B = $3000; Alt_C = $2E00; Alt_D = $2000; Alt_E = $1200; Alt_F = $2100; Alt_G = $2200; Alt_H = $2300; Alt_I = $1700; Alt_J = $2400; Alt_K = $2500; Alt_L = $2600; Alt_M = $3200; Alt_N = $3100; Alt_O = $1800; Alt_P = $1900; Alt_Q = $1000; Alt_R = $1300; Alt_S = $1F00; Alt_T = $1400; Alt_U = $1600; Alt_V = $2F00; Alt_W = $1100; Alt_X = $2D00; Alt_Y = $2C00; Alt_Z = $1500; Alt_1 = $7800; Alt_2 = $7900; Alt_3 = $7A00; Alt_4 = $7B00; Alt_5 = $7C00; Alt_6 = $7D00; Alt_7 = $7E00; Alt_8 = $7F00; Alt_9 = $8000; Alt_0 = $8100; F1 = $3B00; F2 = $3C00; F3 = $3D00; F4 = $3E00; F5 = $3F00; F6 = $4000; F7 = $4100; F8 = $4200; F9 = $4300; F10 = $4400; Shift_F1 = $5400; Shift_F2 = $5500; Shift_F3 = $5600; Shift_F4 = $5700; Shift_F5 = $5800; Shift_F6 = $5900; Shift_F7 = $5A00; Shift_F8 = $5B00; Shift_F9 = $5C00; Shift_F10 = $5D00; Ctrl_AE = $2804; Ctrl_OE = $2714; Ctrl_UE = $1A01; Alt_AE = $285D; Alt_OE = $275B; Alt_UE = $1A40; SH_Alt_AE = $287D; SH_Alt_OE = $277B; SH_Alt_UE = $1A5C; type control_ARRAY = ARRAY[0..4] of smallint; AESPBPtr = ^AESPB; AESPB = record control: ^control_ARRAY; global: PAESGlobal; intin: PAESIntIn; intout: PAESIntOut; addrin: PAESAddrIn; addrout: PAESAddrOut; end; AESOBJECT = TAESOBJECT; AESOBJECTPtr = ^TAESOBJECT; VDIPB = TVDIPB; VDIPBPtr = ^VDIPB; TEDINFO = TTEDINFO; TEDINFOPtr = ^TEDINFO; ICONBLK = TICONBLK; ICONBLKPtr = ^ICONBLK; CICON = TCICON; CICONPtr = ^CICON; CICONBLK = TCICONBLK; CICONBLKPtr = ^CICONBLK; BITBLK = TBITBLK; BITBLKPtr = ^BITBLK; MFORM = TMFORM; MFORMPtr = ^MFORM; USERBLK = TUSERBLK; USERBLKPtr = ^USERBLK; OBSPEC = TOBSPEC; OBSPECPtr = ^OBSPEC; PARMBLK = TPARMBLK; PARMBLKPtr = ^PARMBLK; AESTree = TAESTree; AESTreePtr = ^AESTree; RSHDR = TRSHDR; RSHDRPtr = ^RSHDR; EVENT = TEVENT; EVENTPtr = ^EVENT; MENU = TMENU; MENUPtr = ^MENU; MN_SET = TMN_SET; MN_SETPtr = ^MN_SET; FONT_HDR = TFONT_HDR; FONT_HDRPtr = ^FONT_HDR; MFDB = vdi.TMFDB; MFDBPtr = ^MFDB; global_ARRAY = TAESGlobal; workout_ARRAY = ARRAY[0..56] of smallint; workin_ARRAY = ARRAY[0..10] of smallint; intin_ARRAY = TVDIIntIn; intout_ARRAY = TVDIIntOut; ptsin_ARRAY = TVDIPtsIn; ptsout_ARRAY = TVDIPtsOut; (* * PurePascal has all the AES parameter arrays exposed. * We don't want to do that, because various arrays are * implementation specific. For Compatibility we * need to make the global array available however; *) type AES_block = record global : TAESGlobal; end; var Gem_pb: AES_block; external name 'aes_global'; (* * we also need to make the parameter block available, * so applications can define missing functions * that are not yet implemented here. *) var AES_pb: AESPB; external name 'aespb'; VDI_pb: TVDIPB; external name 'vdipb'; {* * overloaded AES functions that take an AESTreePtr as parameter *} function menu_bar(me_btree: AESTreePtr; me_bshow: smallint): smallint; overload; function menu_icheck(me_ctree: AESTreePtr; me_citem, me_ccheck: smallint): smallint; overload; function menu_ienable(me_etree: AESTreePtr; me_eitem, me_eenable: smallint): smallint; overload; function menu_tnormal(me_ntree: AESTreePtr; me_ntitle, me_nnormal: smallint): smallint; overload; function menu_text(me_ttree: AESTreePtr; me_titem: smallint; me_ttext: String): smallint; overload; function menu_attach(me_flag: smallint; me_tree: AESTreePtr; me_item: smallint; me_mdata: PMENU): smallint; overload; function menu_istart(me_flag: smallint; me_tree: AESTreePtr; me_imenu, me_item: smallint): smallint; overload; function objc_add(ob_atree: AESTreePtr; ob_aparent, ob_achild: smallint): smallint; overload; function objc_delete(ob_dltree: AESTreePtr; ob_dlobject: smallint): smallint; overload; function objc_draw(ob_drtree: AESTreePtr; ob_drstartob, ob_drdepth, ob_drxclip, ob_dryclip, ob_drwclip, ob_drhclip: smallint): smallint; overload; function objc_find(ob_ftree: AESTreePtr; ob_fstartob, ob_fdepth, ob_fmx, ob_fmy: smallint): smallint; overload; function objc_offset(ob_oftree: AESTreePtr; ob_ofobject: smallint; out ob_ofxoff, ob_ofyoff: smallint): smallint; overload; function objc_order(ob_ortree: AESTreePtr; ob_orobject, ob_ornewpos: smallint): smallint; overload; function objc_edit(ob_edtree: AESTreePtr; ob_edobject, ob_edchar: smallint; var ob_edidx: smallint; ob_edkind: smallint): smallint; overload; function objc_change(ob_ctree: AESTreePtr; ob_cobject, ob_cresvd, ob_xclip, ob_yclip, ob_wclip, ob_hclip, ob_cnewstate, ob_credraw: smallint): smallint; overload; function form_do(fo_dotree: AESTreePtr; fo_dostartob: smallint): smallint; overload; function form_center(fo_ctree: AESTreePtr; out fo_cx, fo_cy, fo_cw, fo_ch: smallint): smallint; overload; function form_keybd(fo_ktree: AESTreePtr; fo_kobject, fo_kobnext, fo_kchar: smallint; out fo_knxtobject, fo_knxtchar: smallint): smallint; overload; function form_button(fo_btree: AESTreePtr; fo_bobject, fo_bclicks: smallint; out fo_bnxtobj: smallint): smallint; overload; function rsrc_obfix(re_obtree: AESTreePtr; re_oobject: smallint): smallint; overload; {* * overloaded VDI functions *} procedure v_opnwk(const WorkIn: workin_Array; out handle: smallint; out WorkOut: workout_Array); overload; procedure v_opnvwk(const WorkIn: workin_Array; var handle: smallint; out WorkOut: workout_Array); overload; procedure vq_extnd(handle, owflag: smallint; out WorkOut: workout_Array); overload; procedure vro_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB); overload; procedure vrt_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB; const color_index: ARRAY_2); overload; procedure vqt_extent(handle: smallint; const calcString: String; out extent: ARRAY_8); overload; procedure vqt_f_extent(handle: smallint; const str: String; out extent: ARRAY_8); {* * Utility functions *} procedure SetFreeString(tree: PAESTree; obj: smallint; const str: String); procedure GetFreeString(tree: PAESTree; obj: smallint; out str: String); procedure SetPtext(tree: PAESTree; obj: smallint; const str: String); procedure GetPtext(tree: PAESTree; obj: smallint; out str: String); procedure SetPtmplt(tree: PAESTree; obj: smallint; const str: String); procedure GetPtmplt(tree: PAESTree; obj: smallint; out str :String); procedure SetPvalid(tree: PAESTree; obj: smallint; const str: String); procedure GetPvalid(tree: PAESTree; obj: smallint; out str: String); procedure SetIcontext(tree: PAESTree; obj: smallint; const str: String); procedure GetIcontext(tree: PAESTree; obj: smallint; out str: String); procedure WindSetTitle(handle: smallint; const str: String; var buf: String); procedure WindSetInfo(handle: smallint; const str: String; var buf: String); procedure WindSetNewDesk(tree: PAESTree; firstObj: smallint); implementation type aesstr = array[0..255] of AnsiChar; function string_to_vdi(const src: String; dst: psmallint): smallint; var i, len: longint; begin len:=length(src); for i:=0 to len-1 do dst[i]:=byte(src[i + 1]); string_to_vdi:=len; end; procedure v_opnwk(const WorkIn: workin_Array; out handle: smallint; out WorkOut: workout_Array); begin vdi.v_opnwk(@workin[0], @handle, @workout[0]); end; procedure v_opnvwk(const WorkIn: workin_Array; var handle: smallint; out WorkOut: workout_Array); begin vdi.v_opnvwk(@workin[0], @handle, @workout[0]); end; procedure vq_extnd(handle, owflag: smallint; out WorkOut: workout_Array); begin vdi.vq_extnd(handle, owflag, @workout[0]); end; procedure vro_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB); begin vdi.vro_cpyfm(handle, vr_mode, @pxyarray, @psrcMFDB, @pdesMFDB); end; procedure vrt_cpyfm(handle, vr_mode: smallint; const pxyarray: ARRAY_8; const psrcMFDB, pdesMFDB: TMFDB; const color_index: ARRAY_2); begin vdi.vrt_cpyfm(handle, vr_mode, @pxyarray, @psrcMFDB, @pdesMFDB, @color_index); end; procedure vqt_extent(handle: smallint; const calcString: String; out extent: ARRAY_8); var len: smallint; begin len:=string_to_vdi(calcstring, @vdi_pb.intin^[0]); vdi_pb.control^[0]:=116; vdi_pb.control^[1]:=0; vdi_pb.control^[3]:=len; vdi_pb.control^[5]:=0; vdi_pb.control^[6]:=handle; vdi.vdi; extent[0]:=vdi_pb.ptsout^[0]; extent[1]:=vdi_pb.ptsout^[1]; extent[2]:=vdi_pb.ptsout^[2]; extent[3]:=vdi_pb.ptsout^[3]; extent[4]:=vdi_pb.ptsout^[4]; extent[5]:=vdi_pb.ptsout^[5]; extent[6]:=vdi_pb.ptsout^[6]; extent[7]:=vdi_pb.ptsout^[7]; end; procedure vqt_f_extent(handle: smallint; const str: String; out extent: ARRAY_8); var len: longint; begin len:=string_to_vdi(str, @vdi_pb.intin^[0]); vdi_pb.control^[0]:=240; vdi_pb.control^[1]:=0; vdi_pb.control^[3]:=len; vdi_pb.control^[5]:=0; vdi_pb.control^[6]:=handle; vdi.vdi; extent[0]:=vdi_pb.ptsout^[0]; extent[1]:=vdi_pb.ptsout^[1]; extent[2]:=vdi_pb.ptsout^[2]; extent[3]:=vdi_pb.ptsout^[3]; extent[4]:=vdi_pb.ptsout^[4]; extent[5]:=vdi_pb.ptsout^[5]; extent[6]:=vdi_pb.ptsout^[6]; extent[7]:=vdi_pb.ptsout^[7]; end; function menu_bar(me_btree: AESTreePtr; me_bshow: smallint): smallint; begin menu_bar := aes.menu_bar(@me_btree[0], me_bshow); end; function menu_icheck(me_ctree: AESTreePtr; me_citem, me_ccheck: smallint): smallint; begin menu_icheck := aes.menu_icheck(@me_ctree[0], me_citem, me_ccheck); end; function menu_ienable(me_etree: AESTreePtr; me_eitem, me_eenable: smallint): smallint; begin menu_ienable := aes.menu_ienable(@me_etree[0], me_eitem, me_eenable); end; function menu_tnormal(me_ntree: AESTreePtr; me_ntitle, me_nnormal: smallint): smallint; begin menu_tnormal := aes.menu_tnormal(@me_ntree[0], me_ntitle, me_nnormal); end; function menu_text(me_ttree: AESTreePtr; me_titem: smallint; me_ttext: String): smallint; var s: aesstr; begin s:=me_ttext; menu_text:=aes.menu_text(@me_ttree[0], me_titem, @s); end; function menu_attach(me_flag: smallint; me_tree: AESTreePtr; me_item: smallint; me_mdata: PMENU): smallint; begin menu_attach:=aes.menu_attach(me_flag, @me_tree[0], me_item, me_mdata); end; function menu_istart(me_flag: smallint; me_tree: AESTreePtr; me_imenu, me_item: smallint): smallint; overload; begin menu_istart:=aes.menu_istart(me_flag, @me_tree[0], me_imenu, me_item); end; function objc_add(ob_atree: AESTreePtr; ob_aparent, ob_achild: smallint): smallint; begin objc_add:=aes.objc_add(@ob_atree[0], ob_aparent, ob_achild); end; function objc_delete(ob_dltree: AESTreePtr; ob_dlobject: smallint): smallint; begin objc_delete:=aes.objc_delete(@ob_dltree[0], ob_dlobject); end; function objc_draw(ob_drtree: AESTreePtr; ob_drstartob, ob_drdepth, ob_drxclip, ob_dryclip, ob_drwclip, ob_drhclip: smallint): smallint; begin objc_draw:=aes.objc_draw(@ob_drtree[0], ob_drstartob, ob_drdepth, ob_drxclip, ob_dryclip, ob_drwclip, ob_drhclip); end; function objc_find(ob_ftree: AESTreePtr; ob_fstartob, ob_fdepth, ob_fmx, ob_fmy: smallint): smallint; begin objc_find:=aes.objc_find(@ob_ftree[0], ob_fstartob, ob_fdepth, ob_fmx, ob_fmy); end; function objc_offset(ob_oftree: AESTreePtr; ob_ofobject: smallint; out ob_ofxoff, ob_ofyoff: smallint): smallint; begin objc_offset:=aes.objc_offset(@ob_oftree[0], ob_ofobject, ob_ofxoff, ob_ofyoff); end; function objc_order(ob_ortree: AESTreePtr; ob_orobject, ob_ornewpos: smallint): smallint; begin objc_order:=aes.objc_order(@ob_ortree[0], ob_orobject, ob_ornewpos); end; function objc_edit(ob_edtree: AESTreePtr; ob_edobject, ob_edchar: smallint; var ob_edidx: smallint; ob_edkind: smallint): smallint; begin objc_edit:=aes.objc_edit(@ob_edtree[0], ob_edobject, ob_edchar, ob_edidx, ob_edkind); end; function objc_change(ob_ctree: AESTreePtr; ob_cobject, ob_cresvd, ob_xclip, ob_yclip, ob_wclip, ob_hclip, ob_cnewstate, ob_credraw: smallint): smallint; begin objc_change:=aes.objc_change(@ob_ctree[0], ob_cobject, ob_cresvd, ob_xclip, ob_yclip, ob_wclip, ob_hclip, ob_cnewstate, ob_credraw); end; function form_do(fo_dotree: AESTreePtr; fo_dostartob: smallint): smallint; begin form_do:=aes.form_do(@fo_dotree[0], fo_dostartob); end; function form_center(fo_ctree: AESTreePtr; out fo_cx, fo_cy, fo_cw, fo_ch: smallint): smallint; begin form_center:=aes.form_center(@fo_ctree[0], fo_cx, fo_cy, fo_cw, fo_ch); end; function form_keybd(fo_ktree: AESTreePtr; fo_kobject, fo_kobnext, fo_kchar: smallint; out fo_knxtobject, fo_knxtchar: smallint): smallint; begin form_keybd:=aes.form_keybd(@fo_ktree[0], fo_kobject, fo_kobnext, fo_kchar, fo_knxtobject, fo_knxtchar); end; function form_button(fo_btree: AESTreePtr; fo_bobject, fo_bclicks: smallint; out fo_bnxtobj: smallint): smallint; begin form_button:=aes.form_button(@fo_btree[0], fo_bobject, fo_bclicks, fo_bnxtobj); end; function rsrc_obfix(re_obtree: AESTreePtr; re_oobject: smallint): smallint; begin rsrc_obfix:=aes.rsrc_obfix(@re_obtree[0], re_oobject); end; procedure SetFreeString(tree: PAESTree; obj: smallint; const str: String); var len: SizeInt; p: PAnsiChar; begin len:=length(str); p:=tree^[obj].ob_spec.free_string; move(str[1], p^, len); p[len]:=#0; end; procedure GetFreeString(tree: PAESTree; obj: smallint; out str: String); begin str := tree^[obj].ob_spec.free_string; end; procedure SetPtext(tree: PAESTree; obj: smallint; const str: String); var len: SizeInt; p: PAnsiChar; begin len:=length(str); p:=tree^[obj].ob_spec.ted_info^.te_ptext; if (len >= tree^[obj].ob_spec.ted_info^.te_txtlen) then len := tree^[obj].ob_spec.ted_info^.te_txtlen-1; move(str[1], p^, len); p[len]:=#0; end; procedure GetPtext(tree: PAESTree; obj: smallint; out str: String); begin str := tree^[obj].ob_spec.ted_info^.te_ptext; end; procedure SetPtmplt(tree: PAESTree; obj: smallint; const str: String); var len: SizeInt; p: PAnsiChar; begin len:=length(str); p:=tree^[obj].ob_spec.ted_info^.te_ptmplt; if (len >= tree^[obj].ob_spec.ted_info^.te_tmplen) then len := tree^[obj].ob_spec.ted_info^.te_tmplen-1; move(str[1], p^, len); p[len]:=#0; end; procedure GetPtmplt(tree: PAESTree; obj: smallint; out str: String); begin str := tree^[obj].ob_spec.ted_info^.te_ptmplt; end; procedure SetPvalid(tree: PAESTree; obj: smallint; const str: String); var len: SizeInt; p: PAnsiChar; begin len:=length(str); p:=tree^[obj].ob_spec.ted_info^.te_pvalid; move(str[1], p^, len); p[len]:=#0; end; procedure GetPvalid(tree: PAESTree; obj: smallint; out str: String); begin str := tree^[obj].ob_spec.ted_info^.te_pvalid; end; procedure SetIcontext(tree: PAESTree; obj: smallint; const str: String); var len: SizeInt; p: PAnsiChar; begin len:=length(str); p:=tree^[obj].ob_spec.icon_blk^.ib_ptext; move(str[1], p^, len); p[len]:=#0; end; procedure GetIcontext(tree: PAESTree; obj: smallint; out str: String); begin str := tree^[obj].ob_spec.icon_blk^.ib_ptext; end; procedure WindSetTitle(handle: smallint; const str: String; var buf: String); var len: SizeInt; pstr: PAnsiChar; begin pstr := @buf[0]; len:=length(str); move(str[1], pstr^, len); pstr[len]:=#0; wind_set(handle, WF_NAME, Pointer(pstr)); end; procedure WindSetInfo(handle: smallint; const str: String; var buf: String); var len: SizeInt; pstr: PAnsiChar; begin pstr := @buf[0]; len:=length(str); move(str[1], pstr^, len); pstr[len]:=#0; wind_set(handle, WF_INFO, Pointer(pstr)); end; procedure WindSetNewDesk(tree: PAESTree; firstObj: smallint); begin {$PUSH} {$WARN 4055 OFF} { Conversion between ordinals and pointers is not portable } wind_set(0, WF_NEWDESK, hi(ptruint(tree)), lo(ptruint(tree)), firstObj, 0); {$POP} end; end.