program INFAC2,1.0(101) ! Sample of auto-complete (zip database) !------------------------------------------------------------------------- !EDIT HISTORY ![100] April 29, 2010 05:25 PM Edited by Jack ! Created (based on INFBTN sample) ![101] May 4, 2010 02:45 PM Edited by Jack ! Misc. refinements (such as listing cities already entered at top of list) !------------------------------------------------------------------------ !NOTES: !Requires the USZIP?.ID?[908,48] ISAM file. Provides a more realistic !example of INFLD's Auto-complete operation (with actual file I/O) to !help the user enter a city !------------------------------------------------------------------------- ++include ashinc:ashell.def ++include uszip.def[908,48] ++include ashinc:gtlang.bsi define INF'EXITCODE_CITY = -101 define INF'EXITCODE_ZIP = -102 define INF'EXITCODE_COUNTY = -103 define INF'EXITCODE_STATE = -104 define INF'EXITCODE_OK = -2 define INF'EXITCODE_CANCEL = 1 define INF'EXITCODE_HELP = -1 map1 INFLD'PARAMS map2 INF'ENTRY,S,80 map2 INF'TYPE,S,32 map2 INF'ROW,B,1 map2 INF'COL,B,1 map2 INF'INXCTL,F map2 INF'V,B,1,1 map2 INF'OPCODE,B,1 map2 INF'EXITCODE,F,6 map2 INF'TIMER,F,6 map2 INF'XMAX,B,1,20 map2 INF'XMIN,B,1,0 map2 INF'HLPIDX,S,1024 ! (must be long enough now for context menu too) map2 INF'FUNMAP,B,4,-1 ! you need this to enable fkeys!!! map2 INF'DEFPT,F,6,-1 ! leave these at -1 unless you want map2 INF'MAXPT,F,6,-1 ! special decimal point logic map2 INF'CMDFLG,F map2 MISC map2 ID,B,2 map2 CINF'TYPE,B,4 map2 BTN$,S,1 map2 NEW'OPTIONS1,B,4 map2 NEW'OPTIONS2,B,4 map2 SAVE'OPTIONS1,B,4 map2 SAVE'OPTIONS2,B,4 map2 YESNO$,S,1 map2 DLG$,S,1 map2 MBRC,B,1 map2 KEY,S,32 map2 N,F map2 DLGID,I,2 ! ID of dialog (or 0 if no dialog) map2 CTLID,I,2 map2 EVW'FLAGS,B,4 map2 SAVE'OPCODE,B,1 map1 RECENT'CITY'LIST$,S,0 ! [101] map1 INF'SETDEF,S,0 ! (this could get large, depending on auto-complete list) map1 FIELDS map2 FCITY$,S,30 map2 FZIP$,S,50 map2 FCOUNTY$,S,50 map2 FSTATE$,S,50 map1 ZRECNO,F ! recno var for zip database on error goto TRAP PROGRAM'START: call ADMIN GET'PROGRAM'OPTIONS: ? tab(3,1);"Use buttons for labels (else text) "; call GET'YESNO ! returns YESNO$ if INF'EXITCODE # 0 goto ENDIT if YESNO$="Y" then CINF'TYPE = MBF_BUTTON + MBF_KBD else CINF'TYPE = MBF_STATIC + MBF_LFJUST + MBF_KBD endif ? tab(3,1);tab(-1,9); ! remove the buttons/labels prompt ? tab(3,1);"Use a dialog? "; call GET'YESNO ? tab(3,1);tab(-1,9); ! remove the dialog prompt on INF'EXITCODE goto ENDIT,GET'PROGRAM'OPTIONS,GET'PROGRAM'OPTIONS DLG$ = YESNO$ if DLG$=LANG'YES'CHAR then xcall AUI, AUI_CONTROL, CTLOP_ADD, "dlg1", & "INFAC2 - Auto Completion Example", MBST_ENABLE, & MBF_DIALOG+MBF_SYSMENU+MBF_MAXBUTTON+MBF_ALTPOS, & NUL_CMD$, NUL_FUNC$, DLGID, 4, 1, 17, 75 endif call SCREEN !{Main event loop} INF'EXITCODE = INF'EXITCODE_CITY ! start on city field INF'OPCODE = 1 ! (edit fields!) EVW'FLAGS = EVW_DESCEND+EVW_EDIT+EVW_EXCDFOCUS do xcall AUI,AUI_EVENTWAIT,DLGID,CTLID,INF'EXITCODE,EVW'FLAGS DEBUG.PRINT " AUI_EVENTWAIT exitcode: "+INF'EXITCODE EVW'FLAGS = EVW'FLAGS or EVW_EXCDINOUT ! don't want this on initial set-focus switch INF'EXITCODE case INF'EXITCODE_HELP call DO'HELP exit case INF'EXITCODE_CANCEL exit case INF'EXITCODE_OK exit case INF'EXITCODE_CITY call FCITY exit case INF'EXITCODE_ZIP call FZIP exit case INF'EXITCODE_COUNTY call FCOUNTY exit case INF'EXITCODE_STATE call FSTATE exit endswitch loop until INF'EXITCODE = INF'EXITCODE_CANCEL or INF'EXITCODE = INF'EXITCODE_OK if DLGID then xcall AUI, AUI_CONTROL, CTLOP_DEL, DLGID endif ENDIT: xcall MIAMEX, MX_SETOPTIONS, SAVE'OPTIONS1, SAVE'OPTIONS2 ! restore options ? tab(22,1);"Program end" end TRAP: xcall DERR goto ENDIT ADMIN: ! Turn on AUTOTPRINT and TOKENIZE options (useful for converting ! plain text PRINT statements into GUI ! Notes: ! - AUTOTPRINT is just a convenience; you may prefer to generate ! GUI text controls manually using TPRINT or xcall AUI ! - GUISPCINDENT tokenizes print statements to improve alignment ! (for ATE, this needs to be set on client, and can be done in ! the connection properties) xcall MIAMEX, MX_GETOPTIONS, SAVE'OPTIONS1, SAVE'OPTIONS2 ! save orig NEW'OPTIONS1 = SAVE'OPTIONS1 NEW'OPTIONS2 = SAVE'OPTIONS2 NEW'OPTIONS2 = NEW'OPTIONS2 or GOP2_AUTOTPRINT NEW'OPTIONS2 = NEW'OPTIONS2 or GOP2_GUISPCINDENT xcall MIAMEX, MX_SETOPTIONS, NEW'OPTIONS1, NEW'OPTIONS2 ! Set the background color (bg 0) to match the current windows gray ! Notes: ! - AG_SETWINCLR = 26; ! - We don't care about the "window" (white) and "text" (black) so set to -1 ! - The 4th param is 0 to set the new color ? tab(-10,AG_SETWINCLR);"0,-1,-1,0";chr(127); ? tab(-3,0); ! make sure we are using 0 as the bg (now matches windows gray) ! clear the screen to fill it with the standard windows gray ?TAB(-1,0); ! display a banner in big text (1.5 INF'ROWs high, 150% font scale) xcall AUI, AUI_CONTROL, CTLOP_ADD, "txtBanner1", & "INFAC2 - Test of INFLD Auto-Complete (||a)", MBST_ENABLE, & MBF_STATIC+MBF_LFJUST, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, & 1000, 1, 2250, 80, 2+64, 3+64, FA_HEAVY, 150 return SET'INF'TYPES: ! standard INF'TYPE codes (auto-complete will be added separately) INF'TYPE = "|G" ! Enable Windows style edit INF'TYPE = INF'TYPE+"||T" ! Let ENTER act like TAB INF'TYPE = INF'TYPE+"*" ! General Character INF'TYPE Acceptance INF'TYPE = INF'TYPE+"gh" ! Misc Codes INF'TYPE = INF'TYPE+"123456?Lk" ! Exit Enabling Codes INF'TYPE = INF'TYPE+"|K" ! Windows key conventions INF'TYPE = INF'TYPE+"|]" ! neither pad nor strip if DLG$="Y" then ! INF'TYPE = INF'TYPE + "||F" ! Force fixed pitch (variation, else ! works better in dialogs) INF'TYPE = INF'TYPE + "||f" ! Force fixed pitch endif INF'TYPE = INF'TYPE + "||C" ! Display fields as edit/combo controls return SCREEN: ! Create some label/buttons which will act like F101, F102, F103 ! Notes: ! - AUI,AUI_CONTROL can be replaced by MIAMEX,MX_CONTROL or MIAMEX,119 ! - MBST_ENABLE = 0 (defined in ashell.def) ! - NUL_xxx symbols are also defined in ashell.def (used for clarity) ! - We are using the same ID param, and NUL_CSTATUS, because we don't care ! about the control IDs. ! - Note that the labels are clickable whether as buttons or text; ! we set them to return the 0same exitcodes as the fields ! - Another approach would be to use SBXINP, which combines the ! create of the label and the INFLD operations in one XCALL xcall AUI,AUI_CONTROL,CTLOP_ADD,ID,"&City",MBST_ENABLE,CINF'TYPE,"VK_xF101",NUL_FUNC$, & NUL_CSTATUS,4,10,4,18 xcall AUI,AUI_CONTROL,CTLOP_ADD,ID,"&Zip",MBST_ENABLE,CINF'TYPE,"VK_xF102",NUL_FUNC$, & NUL_CSTATUS,6,10,6,18 xcall AUI,AUI_CONTROL,CTLOP_ADD,ID,"Count&y",MBST_ENABLE,CINF'TYPE,"VK_xF103",NUL_FUNC$, & NUL_CSTATUS,8,10,8,18 xcall AUI,AUI_CONTROL,CTLOP_ADD,ID,"&State",MBST_ENABLE,CINF'TYPE,"VK_xF104",NUL_FUNC$, & NUL_CSTATUS,10,10,10,18 ! Create some icon buttons for ok, cancel, help ! Note: we are using milliINF'ROWs here since 1 INF'ROW is a bit ! short for a button, but 2 might be more room than we need; ! also, the ratio between the height and width is a bit of a ! crap shoot; we could overcome that by specifying the size ! in pixels, but that requires more params on the AUI call ! OK = F2 xcall AUI, AUI_CONTROL, CTLOP_ADD, ID, "check::ashico1", MBST_ENABLE, & MBF_BUTTON+MBF_ICON+MBF_KBD, "VK_F2", NUL_FUNC$, NUL_CSTATUS, & 12000, 5, 13250, 7 ! CANCEL = ESC xcall AUI, AUI_CONTROL, CTLOP_ADD, ID, "delete::ashico1", MBST_ENABLE, & MBF_BUTTON+MBF_ICON+MBF_KBD, "VK_ESC", NUL_FUNC$, NUL_CSTATUS, & 12000, 10, 13250, 12 ! HELP = F1 xcall AUI, AUI_CONTROL, CTLOP_ADD, ID, "help::ashico1", MBST_ENABLE, & MBF_BUTTON+MBF_ICON+MBF_KBD, "VK_xF1", NUL_FUNC$, NUL_CSTATUS, & 12000, 15, 13250, 17 ! display the fields INF'OPCODE = 2 ! (display) call FCITY call FZIP call FCOUNTY call FSTATE return FCITY: INF'ROW = 4 INF'COL = 20 INF'XMAX = 30 INF'ENTRY = FCITY$ call SET'INF'TYPES INF'TYPE = INF'TYPE + "||a)" ! Auto-Complete, enter at end of field INF'HLPIDX=">Use auto-complete list to choose from available US cities" & +chr(126)+"VK_xF101" ! INF'EXITCODE -101 INF'SETDEF = "" ! [101] add current city to recent list if FCITY$ # "" and instr(1,RECENT'CITY'LIST$,FCITY$) < 1 then if len(RECENT'CITY'LIST$) < 150 then RECENT'CITY'LIST$ = RECENT'CITY'LIST$ + pad$(FCITY$,INF'XMAX) + "A," ! [101] color code A endif endif FCITY'AUTO'COMPLETE: call DO'INFLD ! Auto-complete - handle exitcode 30 and 31 if INF'EXITCODE = 30 then ! user paused or hit down arINF'ROW - load up some choices INF'SETDEF = Fn'Load'Auto'Complete'List$(INF'ENTRY, INF'XMAX, RECENT'CITY'LIST$) ! [101] goto FCITY'AUTO'COMPLETE ! return to INFLD with updated list elseif INF'EXITCODE = 31 then ! user hit down arINF'ROW from bottom of list - get more ! first find last item in list N = len(INF'SETDEF) - 2 do while N > 1 if INF'SETDEF[N;1] = "," then KEY = INF'SETDEF[N+1,-3] exit else N = N - 1 endif loop if N < 1 then KEY = INF'ENTRY endif INF'SETDEF = Fn'Load'Auto'Complete'List$(KEY, INF'XMAX, RECENT'CITY'LIST$) ! [101] goto FCITY'AUTO'COMPLETE ! return to INFLD with updated list endif xcall XFOLD,INF'ENTRY if INF'OPCODE # 2 and FCITY$ # INF'ENTRY then ! if city changed, replace the other fields FCITY$ = INF'ENTRY SAVE'OPCODE = INF'OPCODE INF'OPCODE = 2 FZIP$ = "" call FZIP FSTATE$ = "" call FSTATE FCOUNTY$ = "" call FCOUNTY INF'OPCODE = SAVE'OPCODE endif return FZIP: INF'ROW = 6 INF'COL = 20 INF'XMAX = 5 INF'ENTRY = FZIP$ call SET'INF'TYPES INF'HLPIDX=">If more than one city with same name, zip choices will appear in dropdown list"+chr(126)+"VK_xF102" ! INF'EXITCODE -102 INF'SETDEF = Fn'Load'Zip'List'For'City$(FCITY$) if val(INF'ENTRY)=0 and len(INF'SETDEF)>5 then INF'ENTRY = INF'SETDEF[2,instr(2,INF'SETDEF,",")-1] elseif val(INF'ENTRY)=0 ! in case of any other garbage INF'ENTRY = "" endif if len(INF'SETDEF) < 10 then ! if not at least 2 zips that match, don't need combo box INF'SETDEF = "" endif call DO'INFLD if INF'OPCODE # 2 and FZIP$ # INF'ENTRY then FSTATE$ = "" FCOUNTY$ = "" endif FZIP$ = INF'ENTRY return FCOUNTY: if INF'OPCODE = 1 then if FCOUNTY$ = "" then FCOUNTY$ = Fn'Get'County'For'Zip$(FZIP$,FSTATE$) INF'OPCODE = 2 ! update the state field before we call FSTATE ! wait on the county field INF'OPCODE = 1 endif endif INF'ROW = 8 INF'COL = 20 INF'XMAX = 15 INF'ENTRY = FCOUNTY$ call SET'INF'TYPES INF'HLPIDX=">County that the above zip resides in "+chr(126)+"VK_xF103" ! INF'EXITCODE -103 INF'SETDEF = "" call DO'INFLD FCOUNTY$ = INF'ENTRY ! [102] return FSTATE: INF'ROW = 10 INF'COL = 20 INF'XMAX = 2 INF'ENTRY = FSTATE$ call SET'INF'TYPES INF'TYPE = INF'TYPE + "|u" ! upper case INF'HLPIDX=">State abbreviation"+chr(126)+"VK_xF104" ! INF'EXITCODE -104 INF'SETDEF = "" call DO'INFLD FSTATE$ = INF'ENTRY ! [102] return DO'INFLD: xcall INFLD,INF'ROW,INF'COL,INF'XMAX,INF'XMIN,INF'TYPE,INF'ENTRY,INF'INXCTL,INF'V, & INF'OPCODE,INF'EXITCODE,INF'TIMER,INF'CMDFLG,INF'DEFPT,INF'MAXPT, & INF'FUNMAP,INF'SETDEF,0,INF'HLPIDX,INF'XMAX if INF'OPCODE=1 call RESULTS if INF'EXITCODE=-1 call DO'HELP : goto DO'INFLD return GET'YESNO: xcall INFLD,0,0,1,0,"|GYN||C]123",YESNO$,INF'INXCTL,1,1,INF'EXITCODE return RESULTS: ! display INFLD return info; ! note that the following print statements will only align ! the "2nd column" (the data) if the GUI_SPCINDENT (tokenize) ! option is on and there are at least 2 spaces separating ! the 2 "columns" ? TAB(6,55);TAB(-1,9);"INF'ENTRY= "+INF'ENTRY ? TAB(7,55);TAB(-1,9);"INF'INXCTL= "+INF'INXCTL ? TAB(8,55);TAB(-1,9);"INF'EXITCODE= "+INF'EXITCODE return DO'HELP: xcall MSGBOX,"This program illustrates the INFLD auto-complete (||a) feature. " & + "See the source code for details.", "Help", & MBTN_OK, MBICON_ICON, MBMISC_TASKMODAL return !ENDIT: ! ? TAB(-1,28); ! turn cursor back on ! xcall MIAMEX, MX_SETOPTIONS, SAVE'OPTIONS1, SAVE'OPTIONS2 ! restore options ! if DLG$ = "Y" then ! xcall AUI, AUI_CONTROL, CTLOP_DEL, "dlg1" ! remove "dlg1" ! endif ! ? tab(23,1);"End" ! END !-------------------------------------------------------------------------- ! Build an INFLD Auto-Complete INF'SETDEF parameter based on the specified ! starting key$ and field INF'XMAX ! Params: ! key$ [in] - starting key (from field) ! xmax [in] - size of field (or of list items) ! recent'cities$ [in] - list of recently used cities (put at top of list) [101] ! Returns: ! INF'SETDEF param read to pass to INFLD ! Notes: ! We open the USZIP ISAM file here but never close it. (This is a bit ! sloppy but will be handled by the program end.) !-------------------------------------------------------------------------- FUNCTION Fn'Load'Auto'Complete'List$(key$ as s40, & xmax as b2, recent'cities$ as s0) as s0 map1 locals map2 zrecno,f map2 count,i,2 map2 lastcity$,s,40 map1 zrec, ST_ZIPREC call Open'Zip'Database() key$ = ucs(key$) ! keys are all upper case isam #CH_USCITY, 1, key$ if erf(50001) = 33 then ! if key not found,[101] isam #CH_USCITY, 7, key$ ! get next endif if erf(50001) = 0 then ![101] Fn'Load'Auto'Complete'List$ = "1~"+str(xmax)+"~ ~S~~~," ! (simple 1 column version) ![101] below we have a fancier version, with an extra column used to assign a special background color ![101] to the cities we have already entered during the current session, which required a pseudo-col ![101] to define the color Fn'Load'Auto'Complete'List$ = "0~0~ ~H~RGBbg=169,250,183,A~~1~"+str(xmax)+"~ ~S~~"+str(xmax+1)+"~1~ ~Hb~~~," ! [101] ! add in the recent cities list, if present Fn'Load'Auto'Complete'List$ = Fn'Load'Auto'Complete'List$ + recent'cities$ ! [101] ! now loop for up to 20 items count = 0 do while count < 20 and erf(50001)=0 lock #CH_USZIP read #CH_USZIP, zrec if (zrec.CITY # lastcity$) then Fn'Load'Auto'Complete'List$ = Fn'Load'Auto'Complete'List$ + pad$(zrec.CITY,xmax) + " ," ![101] need xtra space for blank color col count = count + 1 lastcity$ = zrec.CITY endif isam #CH_USCITY, 7, key$ loop Fn'Load'Auto'Complete'List$ = Fn'Load'Auto'Complete'List$ + " ," ! 2nd trailing delim [101] (extra blank for no color) endif !TRACE.PRINT "Auto complete list: "+Fn'Load'Auto'Complete'List$ ENDFUNCTION !-------------------------------------------------------------------------- ! Return county for specified zip ! Params: ! zip$ [in] - zip code ! state$ [out] - optional; 2-char state abbrev returned here ! Returns: ! Corresponding county ! Notes: !-------------------------------------------------------------------------- FUNCTION Fn'Get'County'For'Zip$(zip$ as s5, state$ as s2) as s15 map1 zrec, ST_ZIPREC state$ = "" call Open'Zip'Database() isam #CH_USZIP, 1, zip$ if erf(CH_USZIP) = 0 then read #CH_USZIP, zrec Fn'Get'County'For'Zip$ = zrec.COUNTY endif xputarg 2,zrec.STATE ENDFUNCTION !-------------------------------------------------------------------------- ! Build an INFLD Combo INF'SETDEF list of zip codes for specified city ! Params: ! city$ [in] - city ! Returns: ! INF'SETDEF param read to pass to INFLD ! Notes: ! We open the USZIP ISAM file here but never close it. (This is a bit ! sloppy but will be handled by the program end.) ! If only one zip for the specified city, return "" !-------------------------------------------------------------------------- FUNCTION Fn'Load'Zip'List'For'City$(city$ as s40) as s0 map1 locals map2 key$,s,40 map1 zrec, ST_ZIPREC call Open'Zip'Database() city$ = ucs(city$) key$ = strip$(city$) isam #CH_USCITY, 1, key$ ! get position Fn'Load'Zip'List'For'City$ = "," do isam #CH_USCITY, 7, key$ ! get next if erf(CH_USCITY)=0 then lock #CH_USZIP read #CH_USZIP, zrec if (ucs(zrec.CITY) = city$) then Fn'Load'Zip'List'For'City$ = Fn'Load'Zip'List'For'City$ + zrec.ZIP + "," else exit endif endif loop Fn'Load'Zip'List'For'City$ = Fn'Load'Zip'List'For'City$ + "," ENDFUNCTION !-------------------------------------------------------------------------- ! Open the City/Zip ISAM files ! Params: ! None (filespecs are loaded from uszip.def) ! Notes: ! We open the USZIP ISAM file here but never close it. (This is a bit ! sloppy but will be handled by the program end.) If already open, do ! nothing. recno var must be global so as to be common to other routines. ! File channel and other info from uszip.def !-------------------------------------------------------------------------- PROCEDURE Open'Zip'Database() ++extern ZRECNO,f if eof(CH_USZIP) = -1 then ! open zip database if not already if lookup(USZIP_FSPEC$) = 0 then xcall MSGBOX, "This program requires "+USZIP_FSPEC$+". To create the file, download " & + "http://www.microsabio.net/dist/soslib/bldzip.zip, unzip the files into the target directory, " & + "and then RUN BLDZIP.", "Missing City/Zip database", & MBTN_OK, MBICON_STOP, MBMISC_TASKMODAL endif open #CH_USZIP, USZIP_FSPEC$, isam'indexed, ZREC_SIZE, ZRECNO open #CH_USCITY, USCITY_FSPEC$, isam'indexed, ZREC_SIZE, ZRECNO endif ENDPROCEDURE