home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 002 / zipkey44.zip / ZPROG.DOC < prev   
Text File  |  1994-05-18  |  33KB  |  794 lines

  1. PROGRAMMATIC INTERFACE DOCUMENT
  2.  
  3.  
  4. This file is intended for computer programmers who wish to access
  5. ZIPKEY directly from within their programs.  If you are not a
  6. computer programmer, you may ignore this file.
  7.  
  8.  
  9. The ZIPKEY Interrupt
  10.  
  11. When ZIPKEY goes memory-resident (using the ZIPKEY 4 command), it
  12. takes over one of the 8086's interrupts, INT 179 (decimal; it's
  13. B3 in hexadecimal).  This interrupt serves two functions: first,
  14. it is the method by which ZIPKEY detects if it is already
  15. resident.  Second, it provides the interface by which computer
  16. programs can call ZIPKEY directly, to obtain zipcode-related
  17. services.
  18.  
  19. I conducted a survey of numerous computers before selecting INT
  20. 179 to be used by ZIPKEY.  I found no computers or peripherals
  21. that use this interrupt, and I am hopeful that there are none.
  22. If your computer does use INT 179, then ZIPKEY and the device or
  23. program using INT 179 will interfere with each other.  You can
  24. change the interrupt number ZIPKEY uses by modifying the ZIPKEY
  25. program itself: the number 179 is stored in the fourth byte of
  26. the ZIPKEY program code, immediately beyond the three-byte JMP
  27. instruction that begins the program.  This JMP occurs at the very
  28. start of the ZIPKEY.COM file, or immediately beyond the 512-byte
  29. header of the ZIPKEY.EXE file.  You can use a debugger or a hex
  30. editor to modify the byte to an unused interrupt number.
  31.  
  32.  
  33. Testing for ZIPKEY's Presence
  34.  
  35. Before you program attempts to call ZIPKEY, it may wish to verify
  36. that ZIPKEY is resident, and report an error if it isn't.
  37. Otherwise, you program may crash when it tries to call code that
  38. isn't there.
  39.  
  40. You can test for ZIPKEY's presence by examining the INT 179
  41. handler, whose doubleword pointer is stored at offset 179*4 (=716
  42. =02CCH) within segment 0 of the 8086 memory space.  If ZIPKEY is
  43. resident, the doubleword points to its code segment.  Location
  44. 075H within that code segment contains the signature string
  45. ZIPKEY.  Thus, the following code sequence will check for
  46. ZIPKEY's presence:
  47.                                                               P-2
  48.  
  49. OUR_ZIPKEY:                ; our copy of the template
  50.   DB 'ZIPKEY'
  51.  
  52. CHECK_FOR_ZIPKEY:
  53.   PUSH DS                  ; save register value
  54.   SUB AX,AX                ; load zero
  55.   MOV DS,AX                ; point DS to 0 -- 8086 interrupts
  56.   MOV DS,WORD PTR 02CEH    ; fetch the segment part of INT 179
  57.   MOV SI,075H              ; point to signature in segment
  58.   PUSH CS                  ; push our code segment
  59.   POP ES                   ; set ES to our code segment
  60.   MOV DI,OFFSET OUR_ZIPKEY ; now ES:DI points to 'ZIPKEY'
  61.   MOV CX,3                 ; there are 3 words in 'ZIPKEY'
  62.   REPE CMPSW               ; does DS:75H point to 'ZIPKEY'?
  63.   POP DS                   ; restore register before jumping
  64.   JZ ZIPKEY_RESIDENT       ; jump if it does match
  65. ZIPKEY_NOT_RESIDENT:       ; it does not match
  66.  
  67. Following the ZIPKEY signature, at offset 07BH within the ZIPKEY
  68. code segment, is a single byte that is zero in the initial
  69. version of ZIPKEY, but will increment each time I release a
  70. ZIPKEY with new features or any other changes to the programmatic
  71. interface.  That way, if you program needs ZIPKEY to be of a
  72. sufficiently recent version, it can ensure that it is.  (You can
  73. also use the version number returned by the ZK_VERSION function
  74. described shortly.)
  75.  
  76.  
  77. ZIPKEY Calling Conventions
  78.  
  79. ZIPKEY's interface works similarly to that of the MS-DOS
  80. operating system, or the LIM-EMS specification.  The interface is
  81. specified in 8086 assembly language.  You load a function number
  82. into the AH register, and possibly other input parameters into
  83. other registers, then you execute an INT instruction with an
  84. appropriate interrupt number -- in ZIPKEY's case, the INT 179
  85. instruction.
  86.  
  87. When ZIPKEY has completed the function, it returns control to
  88. your program at the instruction following the INT 179.  The
  89. success of the call is indicated by the Carry flag: NoCarry (flag
  90. = 0) indicates success; Carry (flag = 1) indicates failure.  If
  91. the Carry flag is set, AL is usually set to an error code (the
  92. exceptions are those functions which, as mentioned in their
  93. following descriptions, return the state code for a suggested
  94. city).  Here are the possible error codes:
  95.  
  96. 0FDH is returned if ZIPKEY is busy. You will get this error only
  97.      if the program calling ZIPKEY had interrupted another
  98.      program which also happened to be in the middle of a ZIPKEY
  99.      call.  ZIPKEY is not reentrant, so it must refuse calls in
  100.      this situation.  If you think this interrupted-programming
  101.      scenario is possible, you should check for this possibility.
  102.      If ZIPKEY is busy, you should give the interrupted code a
  103.      chance to complete the ZIPKEY call, and try your call again
  104.      later.
  105.                                                               P-3
  106.  
  107. 0FEH is returned if you provided an illegal function number in
  108.      the AH register.
  109.  
  110. 0FFH is returned if the searching function requested failed to
  111.      find a valid entry, or even a suggested value.
  112.  
  113. Here are ZIPKEY's register-preserving conventions:  The AX
  114. register is clobbered by an INT 179 call; but all other 8086
  115. machine registers are preserved unless they are specifically
  116. named as having return values.  If a function returns an error,
  117. such return registers may be clobbered even if they contain no
  118. values in the return case.  For example, the ZK_STCITY_ZIP
  119. function returns values in BH, CX, and DX.  Except for AX, all
  120. other registers not mentioned are preserved (SI,DI,BP,DS,ES).
  121. The BH, CX, and DX registers may be clobbered even if the search
  122. fails (and Carry is returned).
  123.  
  124.  
  125. The ZIPKEY Functions
  126.  
  127. Following are the functions available to you when ZIPKEY is
  128. resident. For each function, you load the input registers with
  129. the values indicated, then invoke INT 179.
  130.  
  131. The names of the functions (ZK_VERSION, ZK_ABBR_ST, etc.) have no
  132. significance to ZIPKEY-- I present them merely as suggested names
  133. if you wish to implement a library of calls; and also so that I
  134. can refer to the functions by name.
  135.  
  136. ZK_VERSION:   returns ZIPKEY version information.
  137.  
  138.   In: AH = 070H
  139.  
  140.  Out: AX = The ZIPKEY program version number, as shown when
  141.          ZIPKEY is invoked or the ZIPKEY window is popped up.  AH
  142.          is the major version number (to the left of the decimal
  143.          point) and AL is the minor version number (to the right
  144.          of the decimal point).  For example, for V1.0 the return
  145.          AX value would be hex 100.
  146.  
  147.       CL = The number of states, (and territories, etc.) in the
  148.          current database.  Each state is assigned an internal
  149.          numeric code by ZIPKEY, that is used by many of the
  150.          functions of ZIPKEY's programmatic interface.  These
  151.          codes range from 0 to CL-1.
  152.  
  153.       DX = The date of the current ZIPKEY.OVL database.  DL is
  154.          the month, ranging from 1 for January to 12 for
  155.          December.  DH is the year minus 1900; e.g., decimal 89
  156.          for 1989.
  157.                                                               P-4
  158.  
  159. ZK_ABBR_ST:   converts a two-letter abbreviation into a state
  160.               code.
  161.  
  162.  In:  AH = 071H
  163.  
  164.       BX = The 2-letter ASCII abbreviation for the state, in
  165.          either upper- or lower-case.  BL is the first letter and
  166.          BH is the second letter.
  167.  
  168. Out:  AL = The ZIPKEY state code, suitable for input to other
  169.          ZIPKEY functions in this chapter.
  170.  
  171.          AL = 0FFH with the Carry flag set if not found.
  172.  
  173.  
  174. ZK_ST_ABBR:   converts a state code into a two-letter
  175.               abbreviation.
  176.  
  177.  In:  AH = 072H
  178.  
  179.       BL = The ZIPKEY state code, ranging from 0 through CL-1,
  180.          where CL is returned by ZK_VERSION.
  181.  
  182. Out:  AX = The 2-letter ASCII abbreviation, upper case.  AL is
  183.       the first letter and AH is the second letter.
  184.  
  185.       The Carry flag is set if the input state code BL was
  186.       invalid.
  187.  
  188.  
  189. ZK_ST_NAME:   converts a state code into a full state name.
  190.  
  191.  In:  AH = 073H
  192.  
  193.       BL = The ZIPKEY state code, as returned by ZK_ABBR_ST.
  194.  
  195.       ES:DI points to the buffer to contain the returned state
  196.       name.
  197.  
  198. Out:  The full state name is output to ES:DI-pointed memory. DI
  199.       is advanced beyond the output.
  200.  
  201.     The Carry flag is set if the input state code BL was invalid.
  202.                                                               P-5
  203.  
  204. ZK_ZIP_DIGITS:  converts zipcode DXCH into a ASCII digits string.
  205.  
  206.  In:  AH = 074H
  207.  
  208.       DX = The zip region, ranging from 0 to 999.
  209.  
  210.       CH = The last 2 digits of the zipcode, from 0 to 99.  Or,
  211.            if you want only 3 digits output, set CH to 255.
  212.  
  213. Out:  The 5 ASCII decimal digits of the zipcode are output to
  214.       ES:DI-pointed memory.  DI advanced beyond the output.
  215.  
  216.       The Carry flag is set if DX was greater than 999.
  217.  
  218.       NOTE this is not really a database function-- it is just
  219.       an unpacking function provided for convenience.
  220.  
  221.  
  222. ZK_ZIP_ST:   looks up the state code for zipcode DXCH.
  223.  
  224.  In:  AH = 075H
  225.  
  226.       DX = The zip region, ranging from 0 to 999.
  227.  
  228.       CH = The last 2 digits of the zipcode, from 0 to 99.
  229.  
  230. Out:  AL = the ZIPKEY state code.
  231.  
  232.       BX = the area code.
  233.  
  234.       The Carry flag is set, and AL=0FFH, if the zipcode
  235.       region (the first three digits) is invalid.
  236.  
  237.       Note: for speed, this routine does not check for validity
  238.       of the individual zipcode: it looks at only the zip
  239.       region and the state-exceptions list.  If you wish to
  240.       check the validity of a zipcode, use ZK_ZIP_CITY instead.
  241.                                                               P-6
  242.  
  243. ZK_ZIP_CITY: looks up the state and city for zipcode DXCH.
  244.  
  245.  In:  AH = 076H
  246.  
  247.       DX = The zip region, ranging from 0 to 999.
  248.  
  249.       CH = The last 2 digits of the zipcode, from 0 to 99.
  250.  
  251.       ES:DI points to the buffer to contain the returned city
  252.       name.
  253.  
  254. Out:  The ZIPKEY state code is returned in the AL register, the
  255.       timezone code in the AH register, and the area code (decimal
  256.       value) in the BX register.  The timezone code is 2*H + D,
  257.       where H is the timezone hour (4 for Pacific, 7 for Eastern,
  258.       etc.), and D is 1 if daylight savings is observed, 0 if not.
  259.       The city name is output to ES:DI-pointed memory.  DI is
  260.       advanced beyond the output.  To ensure that the name does
  261.       not exceed a maximum width, you can set the width using the
  262.       ZK_RESTORE function.  The Carry flag is set if the zipcode
  263.       was not found, with AL/DI set to the suggested state/city if
  264.       there is one.  AL is set to 0FFH if there is no suggested
  265.       city.
  266.  
  267.       NOTE that a previous call to ZK_ZIP_ST can and should be
  268.       made if you wish to suppress output for the not-found-but-
  269.       suggested case.
  270.  
  271.  
  272. ZK_ZIP_KEYS: plays the back exit key BX for the entry with
  273.              zipcode DXCH.
  274.  
  275.  In:  AH = 077H
  276.  
  277.       BX = The 16-bit BIOS keycode for a defined ZIPKEY alternate
  278.          exit key.  This is the code returned in the AX register
  279.          after you call the keyboard service routine (MOV AH,0
  280.          followed by INT 016H).  For example, the code for the F1
  281.          function key on a 100% IBM-compatible is 03B00H; add
  282.          0100H for subsequent function keys.
  283.  
  284.       DX = The zip region, ranging from 0 to 999.
  285.  
  286.       CH = The last 2 digits of the zipcode, from 0 to 99.
  287.  
  288. Out:  If there is a failure with no suggested city, ZIPKEY
  289.       returns Carry to the caller.  Otherwise, it returns
  290.       NoCarry, and the zipcode specification defined by the BX
  291.       exit-key is inserted into the BIOS keystrokes buffer, as if
  292.       a user had popped up the ZIPKEY window, typed in the
  293.       zipcode, and exited with the BX exit key.
  294.                                                               P-7
  295.  
  296. ZK_STCITY_ZIP:  looks up the zipcodes for a given state and city.
  297.  
  298.  In:  AH = 078H
  299.  
  300.       BL = The ZIPKEY state code for the city to be looked up.
  301.  
  302.       DS:SI points to the city-name specification.  The
  303.           specification is a string of ASCII characters,
  304.           terminated by a carriage-return (0DH) if the complete
  305.           name has been given, terminated by a null (00H) if
  306.           ZIPKEY should match any city whose name begins with the
  307.           specification, whether or not that is the complete city
  308.           name.  Letters in the string can be in either upper- or
  309.           lower-case.  ZIPKEY will also unabbreviate the string,
  310.           as described in Chapter 2.
  311.  
  312. Out:  ZIPKEY accumulates a list of all cities that match the
  313.       specification given.  The list is sorted first
  314.       alphabetically by city name, then numerically by zipcode.
  315.       Each entry on the list is a range of zipcodes for a city
  316.       that matches the specification.  If the first and last
  317.       zipcodes in the range are the same, the range consists of
  318.       just the one zipcode.  If they are different, then they
  319.       both represent valid codes for a matching city.  Any
  320.       zipcodes between the first and last may be either valid
  321.       zipcodes for the same city, or undefined zipcodes.
  322.  
  323.       The capacity of ZIPKEY's matching-entries buffer is 50. If
  324.       there are more than 50 entries for the specification,
  325.       ZIPKEY will return a count of 51 entries.  You may make
  326.       calls to ZK_CASE_ZIP to determine the entries returned, but
  327.       be aware that unless the complete count happened to be 51,
  328.       the list is incomplete.  The only way to obtain the
  329.       complete list of entries is to extend the city-name
  330.       specification by adding one or more letters in all possible
  331.       combinations.
  332.  
  333.       The zipcode range for the first entry is returned with this
  334.       call.  To obtain the remaining entries, you make repeated
  335.       calls to ZK_CASE_ZIP.  To obtain a readable display for
  336.       each entry, you call ZK_ZIP_CITY, ZK_ZIP_ST, and
  337.       ZK_ZIP_DIGITS.
  338.  
  339. The return register values are:
  340.  
  341.       BH = The number of matching entries (Carry set if BH=0). If
  342.          ZIPKEY's entries-buffer overflowed, BH is set to 51 (see
  343.          the above discussion about capacity).
  344.  
  345.       DX = The zip region (0 to 999) of the first entry.
  346.  
  347.       CL = The value of the bottom two digits for the first
  348.          zipcode in the range.
  349.  
  350.       CH = The value of the bottom two digits for the last
  351.          zipcode in the range.
  352.                                                               P-8
  353.  
  354. ZK_CITY_ZIP:   looks up zipcodes for a given city.
  355.  
  356.  In:  AH = 079H
  357.  
  358.       BL = The ZIPKEY state code of the first state to be
  359.          searched.
  360.  
  361.       DS:SI points to the city-name specification, just as in
  362.          ZK_STCITY_ZIP.
  363.  
  364. Out:  ZIPKEY accumulates a list of zipcode ranges, just as in
  365.       ZK_STCITY_ZIP.  With this function, however, if no matching
  366.       entries are found for state BL, then BL is incremented to
  367.       search in the next state.  Searching continues until either
  368.       a match is found or the last state code is reached.  If
  369.       there is no matching entry for the last state, ZIPKEY
  370.       returns AL=0FFH with the Carry flag set.  This differs from
  371.       the city-only search that is initiated interactively from
  372.       ZIPKEY's popup window-- the interactive search cycles
  373.       around to the first state and continues looking from there.
  374.  
  375.       To get a complete list of matching cities for all states,
  376.       you call this function first with BL=0, then repeat the
  377.       call with BL set to the previous returned AL+1, until you
  378.       get a failed find.
  379.  
  380.  
  381. The return register values are:
  382.  
  383.       AL = The ZIPKEY state code of the first matching state. AL
  384.          is set to 0FFH with Carry set if no state was found.
  385.  
  386.       BH = The number of matching entries (Carry set if BH=0). If
  387.          ZIPKEY's entries-buffer overflowed, BH is set to 51.
  388.  
  389.       DX = The zip region (0 to 999) of the first entry.
  390.  
  391.       CL = The value of the bottom two digits for the first
  392.          zipcode in the range.
  393.  
  394.       CH = The value of the bottom two digits for the last zipcode
  395.          in the range.
  396.                                                               P-9
  397.  
  398. ZK_CASE_ZIP:  fetches an entry from a previous ZK_(ST)CITY_ZIP
  399.               call.
  400.  
  401.  In:  AH = 07AH
  402.  
  403.       BL = a case number, from 0 to BH-1, where BH is the number
  404.          returned by the last call to ZK_STCITY_ZIP or
  405.          ZK_CITY_ZIP.
  406.  
  407. Out:  AL = The ZIPKEY state code for this entry.  Note that this
  408.          is the same value for all entries returned by a given
  409.          call to ZK_STCITY_ZIP or ZK_CITY_ZIP.
  410.  
  411.       DX = The zip region (0 to 999).
  412.  
  413.       CL = The bottom 2 digits (0 to 99) of the first zipcode in
  414.          the range.
  415.  
  416.       CH = the bottom 2 digits (0 to 99) of the last zipcode in
  417.          the range. CH = CL if there is only one zipcode.
  418.  
  419.  
  420. ZK_SAVE: fetches values necessary to save ZIPKEY's context.
  421.  
  422.  In:  AH = 07BH
  423.  
  424. Out:  BL = maximum number of characters for a ZK_ZIP_CITY city name.
  425.  
  426.       BH = the ZIPKEY state code for the last city-name search.
  427.  
  428.       BH = 0FF if there is no previous ZK_STCITY_ZIP or
  429.          ZK_CITY_ZIP call.
  430.  
  431.       CXDX = internal codes identifying the last city search
  432.  
  433.       This function is provided just in case somebody wishes to
  434.       incorporate ZIPKEY into a multitasking system, in which
  435.       more than one task might be using ZIPKEY.  The task-
  436.       switching code must call ZK_SAVE, record BX,CX, and DX as
  437.       part of the task state, and feed those values to ZK_RESTORE
  438.       before restarting the task.
  439.  
  440.       ZK_SAVE can also be used to read the current setting for
  441.       the maximum city width, returned in the BL register.
  442.                                                              P-10
  443.  
  444. ZK_RESTORE: restores ZIPKEY's context from a previous ZK_SAVE call.
  445.  
  446.  In:  AH = 07CH
  447.  
  448.       BL = the maximum number of characters for a city name.
  449.  
  450.       BH = the ZIPKEY state code returned by a previous ZK_SAVE
  451.          call.
  452.  
  453.       BH = 0FF if you are just setting the city width.
  454.  
  455.       CXDX = internal codes returned by a previous ZK_SAVE call.
  456.  
  457. Out:  Carry if BH,CX,DX are not codes which could have been
  458.       returned by a previous ZK_SAVE call
  459.  
  460.       This function will be used most often to set the maximum
  461.       city width.  It is also used in multitasking systems, as
  462.       described under the previous function ZK_SAVE.
  463.  
  464.  
  465. ZK_POPUP:   pops up a ZIPKEY window from a program.
  466.  
  467.  In:  AH = 07DH
  468.  
  469.       BL = an index number if you wish to simulate the pressing of
  470.          a hotkey.
  471.  
  472.       BL = 0FF for immediate popup with nothing played back after
  473.          a confirming Enter key.
  474.  
  475. Out:  ZIPKEY takes action as if the hotkey indexed by BL has been
  476.       pressed.  This typically includes popping up a window,
  477.       waiting for the user to type a zipcode specification, and
  478.       playing back an indicated sequence through the BIOS
  479.       keystrokes buffer.  The values of BL are defined by the
  480.       listing of hotkeys available from the configuration editing
  481.       menu: BL=0 for the first hotkey, BL=1 for the second, etc.
  482.       If BL is not a valid index ZIPKEY pops up a window, then
  483.       plays back nothing if a confirming Enter is given (ZIPKEY
  484.       will play back alternate exit keys, however).  ZIPKEY does
  485.       not return from this interrupt call until the window is
  486.       popped away-- then it returns NoCarry.
  487.                                                              P-11
  488.  
  489. ZK_REGION_CITY:   outputs the name of the primary city for a
  490.                   zipcode region.
  491.  
  492.  In:  AH = 07EH
  493.  
  494.       DX = The zip region, ranging from 0 to 999.
  495.  
  496.       ES:DI points to the buffer to contain the returned city
  497.          name.
  498.  
  499. Out:  AL = The ZIPKEY state code for the region if the region
  500.       exists.  BX is set to the area code.
  501.       The name of primary city for this region is output
  502.       to ES:DI-pointed memory.  DI is advanced beyond the output.
  503.       AL = 0FF with the Carry flag set if the region does not
  504.       exist.
  505.  
  506.  
  507. ZK_SWITCH:   enables/disables hotkeys and/or DOS recursion checking.
  508.  
  509.  In:  AH = 07FH
  510.  
  511.       BL = a control code:
  512.             0 for turn off hotkeys
  513.             1 for turn on hotkeys
  514.             2 for no change, just return hotkey status
  515.             3 for toggle hotkey status
  516.             6 for disabling DOS recursion checking
  517.  
  518. Out:  The activation of hotkeys is disabled/enabled/reported.
  519.       When a hotkey is disabled ZIPKEY ignores it, and it reverts
  520.       to its non-ZIPKEY functionality.  AL is returned set to the
  521.       hotkeys status: 0 for off (disabled), 1 for on (enabled).
  522.  
  523.       If BL=6, ZIPKEY's program interface
  524.       (INT 179) no longer checks
  525.       to see if DOS is busy and cannot be called.  It is the calling
  526.       program's responsibility to insure that DOS can be called.
  527.  
  528. ZK_AREA_ST:   Delivers the state associated with area code BX.
  529.  
  530.  In:  AH = 080H
  531.       BX = area code (decimal integer)
  532.  
  533. Out:  AL = the ZIPKEY state code for the area code, if the area code
  534.       exists.  DX is set to the first zip region associated with that
  535.       state, and CX to the number of zip regions until the last
  536.       region associated with the state.  You must make CX subsequent
  537.       calls to ZK_REGION_CITY to find which regions are actually within
  538.       the state, and/or contain the area code wanted.
  539.  
  540.       If the area code is Canadian, we return a special state code
  541.       that will be honored by ZK_ST_ABBR and ZK_ST_NAME, but the
  542.       region DX is set to 1000.  If the area code does not exist,
  543.       we return Carry, AL=0FFH and DX=1001.
  544.                                                              P-12
  545.  
  546. Sample Program Code
  547.  
  548. Following are fragments of assembly-language code that call
  549. ZIPKEY's programmatic interface.  I've tried to make them
  550. compatible with all the major assemblers, although they are
  551. tested only against my A86 assembler. If you do use my A86
  552. assembler, and you reuse the local labels L3, L4, L6, L8, and L10
  553. elsewhere in your program, you should insert ">" into their
  554. forward references in the following code: JC >L3; JC >L4; JMP
  555. >L6, JNE >L8, JE >L10.
  556.  
  557. RO_NAME:
  558.   DB 'RO',0
  559. NOME_NAME:
  560.   DB 'nome',0DH
  561.  
  562.  
  563. ; output a list of states to memory at 08000H
  564.  
  565. L0:
  566.   MOV AH,070H       ; ZIPKEY function number ZK_VERSION
  567.   INT 179           ; fetch the version information
  568.   MOV CH,0          ; extend states count CL to CX
  569.   MOV BL,0          ; load the first state code
  570.   MOV DI,08000H     ; load the output pointer
  571. L1:                 ; loop here to output each state name
  572.   MOV AH,072H       ; ZIPKEY function number ZK_ST_ABBR
  573.   INT 179           ; fetch the state abbreviation
  574.   STOSW             ; output the abbreviation
  575.   MOV AL,' '        ; load blank
  576.   STOSB             ; output an intervening blank
  577.   MOV AH,073H       ; ZIPKEY function number ZK_ST_NAME
  578.   INT 179           ; output the full state name
  579.   MOV AX,0A0DH      ; load CRLF
  580.   STOSW             ; output CRLF to end this line
  581.   INC BL            ; increment BL to the next state code
  582.   LOOP L1           ; loop to output the next state
  583.                                                              P-13
  584.  
  585. ; output to memory the list of valid zipcodes for region 474
  586.  
  587.   MOV DX,474        ; load the region number
  588.   MOV DI,08000H     ; load the output pointer
  589.   MOV CH,0          ; the first zipcode has bottom digits 00
  590. L2:                 ; loop here to output each entry
  591.   MOV AH,075H       ; ZIPKEY function number ZK_ZIP_ST
  592.   INT 179           ; check the validity of this zipcode
  593.   JC L3             ; skip if this is not a valid zipcode
  594.   MOV BL,AL         ; zipcode valid: copy state code to BL
  595.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  596.   INT 179           ; output the zipcode digits
  597.   MOV AL,' '        ; load blank
  598.   STOSB             ; output an intervening blank
  599.   CALL CITY_ST_CRLF ; output the city, state, and CRLF
  600. L3:
  601.   INC CH            ; increment the bottom 2 digits counter
  602.   CMP CH,100        ; have we completed the region?
  603.   JB L2             ; loop if not, to output the next line
  604.  
  605.  
  606. ; output a list of Illinois cities starting with RO
  607.  
  608.   MOV DI,08000H     ; load the output pointer
  609.   MOV BX,'LI'       ; characters IL are reversed on the 8086
  610.   MOV AH,071H       ; ZIPKEY function number ZK_ABBR_ST
  611.   INT 179           ; fetch the state code for this abbreviation
  612.   MOV BL,AL         ; copy the state code to BL
  613.   PUSH CS           ; push our code segment
  614.   POP DS                 ; set DS to our code segment
  615.   MOV SI,OFFSET RO_NAME  ; point to "RO" city specification
  616.   MOV AH,078H            ; ZIPKEY function number ZK_STCITY_ZIP
  617.   INT 179           ; get the list of entries for this city
  618.   JC L4             ; skip if the list was empty
  619.   CALL OUT_ENTRIES
  620. L4:
  621.  
  622.  
  623. ; output a list of Nomes in the United States
  624.  
  625.   MOV DI,08000H            ; load the output pointer
  626.   PUSH CS                  ; push our code segment
  627.   POP DS                   ; set DS to our code segment
  628.   MOV SI,OFFSET NOME_NAME  ; point to "Nome" specification
  629.   MOV BL,0                 ; first state code is zero
  630.   JMP L6                   ; jump into loop
  631.  
  632. L5:                        ; loop here for each matching state
  633.   PUSH AX                  ; save the state code
  634.   CALL OUT_ENTRIES         ; output the entries for this state
  635.   POP BX                   ; restore the state code to BL
  636.   INC BX                   ; increment to the next state
  637. L6:
  638.   MOV AH,079H              ; ZIPKEY function number ZK_CITY_ZIP
  639.   INT 179                  ; find a state with the desired city
  640.   JNC L5                   ; loop if found, to make display
  641.                                                              P-14
  642.  
  643. ; set the maximum city width to 17
  644.  
  645.   MOV BL,17         ; load the desired city width
  646.   MOV BH,0FFH       ; code signals that we load width only
  647.   MOV AH,07CH       ; ZIPKEY function number ZK_RESTORE
  648.   INT 179           ; set the city width
  649.  
  650.  
  651. ; save and restore ZIPKEY context
  652.  
  653.   MOV AH,07BH       ; ZIPKEY function number ZK_SAVE
  654.   INT 179           ; fetch the ZIPKEY context
  655.   PUSH BX           ; push the context onto our stack
  656.   PUSH CX
  657.   PUSH DX
  658. ; ....
  659.   POP DX            ; pop the saved context
  660.   POP CX
  661.   POP BX
  662.   MOV AH,07CH       ; ZIPKEY function number ZK_RESTORE
  663.   INT 179           ; restore the ZIPKEY context
  664.  
  665.  
  666. ; popup a window as if the first hotkey were pressed
  667.  
  668.   MOV AH,07DH       ; ZIPKEY function number ZK_POPUP
  669.   MOV BL,0          ; index for the first hotkey is zero
  670.   INT 179           ; popup the ZIPKEY window
  671.  
  672.  
  673. ; insert keystrokes for zipcode 47401, as if alternate
  674. ;   exit key F1 had been pressed
  675.  
  676.   MOV DX,474        ; load the region number 474
  677.   MOV CH,01         ; load the last two digits 01
  678.   MOV BX,03B00      ; load the BIOS code for the F1 key
  679.   MOV AH,077H       ; ZIPKEY function number ZK_ZIP_KEYS
  680.   INT 179           ; insert keystrokes for 47401 entry
  681.  
  682.  
  683. ; toggle the activation of ZIPKEY's hotkeys
  684.  
  685.   MOV BL,3          ; control code for "toggle"
  686.   MOV AH,07FH       ; ZIPKEY function number ZK_SWITCH
  687.   INT 179           ; toggle the activation of hotkeys
  688.                                                              P-15
  689.  
  690. ; output to DI a list of sample cities for area code 512
  691.  
  692.   MOV BP,512      ; load the area code number
  693.   MOV DI,08000H   ; load the output pointer
  694.   MOV DX,BP       ; set DX to the area code
  695.   CALL OUT_DX3    ; output the area code
  696.   MOV BX,BP       ; copy the area code to BX, for ZK_AREA_ST
  697.   MOV AH,080H     ; function code for ZK_AREA_ST
  698.   INT 179         ; set AL to the state code for area code BX
  699.   JC OUT_CRLF     ; exit if the area code did not exist
  700.   MOV BL,AL       ; we have a state code: copy it to BL
  701.   MOV AH,073H     ; function code for ZK_ST_NAME
  702.   INT 179         ; output the name of this area code's state
  703.   CALL OUT_CRLF   ; output a CRLF to complete the header line
  704.   CMP DX,1000     ; was it a Canadian area code?
  705.   JAE OUT_CRLF    ; skip if it was
  706. L7:               ; loop here to check each zip region
  707.   PUSH DI         ; save the output pointer
  708.   ADD DI,6        ; advance pointer to the city-name column
  709.   MOV AH,07EH     ; function code for ZK_REGION_CITY
  710.   INT 179         ; output the city name for this region
  711.   CMP BX,BP       ; does the city have the correct area code?
  712.   MOV AX,DI       ; save the end-of-line output pointer
  713.   POP DI          ; restore the start-of-line output pointer
  714.   JNE L8          ; cancel the line if it wasn't our area code
  715.   PUSH AX         ; we do have our area code: save end pointer
  716.   MOV AX,'  '     ; load two blanks
  717.   STOSW           ; output a two-blank indentation
  718.   CALL OUT_DX3    ; output the area code
  719.   POP DI          ; restore the end-of-line pointer
  720.   CALL OUT_CRLF   ; output the terminating CRLF
  721. L8:
  722.   INC DX          ; advance DX to the next zip region
  723.   LOOP L7         ; loop to check the next region
  724.                                                              P-16
  725.  
  726. CITY_ST_CRLF:     ; subroutine for outputting a city line
  727.   PUSH DX         ; preserve register across call
  728.   MOV AH,076H     ; ZIPKEY function number ZK_ZIP_CITY
  729.   INT 179         ; output the city name
  730.   MOV DX,BX       ; copy the area code to DX, for output
  731.   MOV BL,AL       ; copy the state code to BL
  732.   MOV AL,' '      ; load blank
  733.   STOSB           ; output an intervening blank
  734.   MOV AH,072H     ; ZIPKEY function number ZK_ST_ABBR
  735.   INT 179         ; fetch the state abbreviation
  736.   STOSW           ; output the state abbreviation
  737.   MOV AX,'( '     ; load a space and a left paren
  738.   STOSW           ; output a space and a left paren
  739.   CALL OUT_DX3    ; output the area code
  740.   DEC DI          ; retract the trailing blank
  741.   MOV AL,')'      ; load a right paren
  742.   STOSB           ; output a right paren
  743.   POP DX          ; restore clobbered register
  744. OUT_CRLF:         ; subroutine for outputting line terminator
  745.   MOV AX,0A0DH    ; load CRLF
  746.   STOSW           ; output CRLF
  747.   RET
  748.  
  749.  
  750. OUT_DX3:            ; subroutine for outputting 3-digit DX
  751.   PUSH CX           ; preserve register across call
  752.   MOV CH,0FFH       ; CH code suppresses the final two digits
  753.   MOV AH,074H       ; function code for ZK_ZIP_DIGITS
  754.   INT 179           ; output the 3-digit code
  755.   MOV AL,' '        ; load blank
  756.   STOSB             ; output a trailing blank
  757.   POP CX            ; restore clobbered register
  758.   RET
  759.                                                              P-17
  760.  
  761. OUT_ENTRIES:        ; subroutine for outputting a cities-range
  762.   MOV BL,0          ; load the first entry number
  763. L9:                 ; loop here to output each entry
  764.   PUSH BX           ; save the entry number during output
  765.   PUSH DI           ; save the starting output pointer
  766.   ADD DI,5          ; advance beyond the zipcode we will output
  767.   MOV AX,'  '       ; load blanks
  768.   STOSW             ; blank out the trailing range slot
  769.   STOSW             ; slot plus trailing blank are 4 characters
  770.   POP DI            ; restore the pointer to the line start
  771.   MOV AH,07AH       ; ZIPKEY function number ZK_CASE_ZIP
  772.   INT 179           ; look up this entry
  773.   MOV BL,AL         ; copy the state code to BL
  774.   CMP CL,CH         ; is there only one zipcode?
  775.   JE L10            ; skip if single zipcode: slot stays blank
  776.   PUSH DI           ; it is a range: save output pointer
  777.   ADD DI,3          ; advance the output pointer
  778.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  779.   INT 179           ; output the end-value zipcode digits
  780.   POP DI            ; restore starting output pointer
  781.   ES MOV BYTE PTR [DI+5],'-' ; place the trailing hyphen
  782.   MOV CH,CL         ; copy the start-value to CH
  783. L10:
  784.   MOV AH,074H       ; ZIPKEY function number ZK_ZIP_DIGITS
  785.   INT 179           ; output the start-value zipcode digits
  786.   ADD DI,4          ; advance beyond the end-value slot
  787.   CALL CITY_ST_CRLF ; output the city, state, CRLF
  788.   POP BX            ; restore the entry number BL
  789.   INC BL            ; increment the entry number
  790.   CMP BL,BH         ; have we exhausted the entries?
  791.   JB L9             ; loop if not, to output the next entry
  792.   RET
  793.  
  794.