1
0
mirror of synced 2026-01-13 15:37:38 +00:00
Interlisp.medley/library/MULTI-ALIST.TEDIT
rmkaplan 82fc95ce18
rmk122--Next round on fonts and MCCS (#2280)
* A revision to the font, Unicode, Tedit, and other modules to implement the MCCS character coding as the standard for internal text strings.  MCCS is a variant of XCCS with arrows switched with circumflex/underscore and $ switched with currency, and allows for additional code assignments over time. :MCCS replaces :XCCS as the default external format, especially for source files.  The file XCCS is removed in favor of the file MCCS, which includes the XCCS external format for backward compatibility.

* This includes a single Medley-font formatted font file for each of the family/size/face display fonts.  The glyph assignments correspond to the MCCS character encoding (except for fonts with idiosyncratic encodings--Hippo, Symbol).  All charsets from legacy font files are included in each file, and the character sets and glyphs in each file have also been extended by offline coercion from related families (e.g. Glyphs not in legacy Terminal are taken from legacy Modern). There should be fewer black boxes, and character-display shouldn't change when you switch fonts.

* The Unicode mapping tables have been redefined to set up correspondences between Unicode and MCCS, not XCCS.  Separate XCCS to/from MCCS mapping functions are provided in the file MCCS; they are no longer included in INTERPRESS.

* TEDIT converts characters in legacy fonts to their new MCCS codes as it reads formatted files, marks the file as MCCS compatible and preserves the new codes on writing.

* Default keyboard assignments produce the MCCS uparrow and leftarrow for shift-6 and shift-hyphen, use Function-6 for circumflex and Function-10 for underscore.

See documentation in FONTCODECHANGES.TEDIT MCCS.TEDIT MEDLEYFONTFORMAT.TEDIT in docs/internal, and library/UNICODE.TEDIT.
2025-10-20 17:17:34 -07:00

106 lines
13 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Medley MULTI-ALIST
2
4
1
MULTI-ALIST
1
4
By Ron Kaplan
This document was last edited in August 2025.
Introduction
MULTI-ALIST provides a collection of macros and related functions that make it easy to store and retrieve items in a hierarchical, multi-level association list indexed by an arbitrary number of keys. For example, a new font descriptor FD can be added to the database that caches the in-memory fonts by the expression
(PUTMULTI \FONTSINCORE FAMILY SIZE FACE ROTATION DEVICE FD)
and FD can then be retrieved by the expression
(GETMULTI \FONTSINCORE FAMILY SIZE FACE ROTATION DEVICE).
As another example, the macro PUSHMULTI adds a new value to a list of indexed items and GETMULTI then returns the collection of items at that index. If the variable WINES is initialized to NIL and the following expressions are evaluated
(PUSHMULTI WINES 'RED 'DRY 'FRENCH 'CABERNET)ÿÿ
ÿ(PUSHMULTI WINES 'RED 'DRY 'FRENCH 'PINOT-NOIR)ÿÿ
ÿ(PUSHTMULTI WINES 'WHITE 'DRY 'FRENCH 'CHARDONNAY)
WINES will become the multi-alist
((RED (DRY (FRENCH PINOT-NOIR CABERNET)))ÿÿ
ÿ (WHITE (DRY (FRENCH CHARDONNAY)))
and
(GETMULTI WINES 'RED 'DRY 'FRENCH )
will return the list (PINOT-NOIR CABERNET).
Creating multi-alist paths and inserting values
The basic macro PUTMULTI makes sure that there is a multi-alist path for a sequence of keys running from a commonLisp PLACE. It then inserts the value VAL at the bottom of the path, at the pair headed by KEYn. VAL replaces any previous value at that position.
(PUTMULTI PLACE KEY1...KEYn VAL) [Macro]
PLACE is a form that can be passed as the first argument of CL:SETF. VAL replaces any previous item at the KEYn position. The value of PUTMULTI is VAL. PUTMULTI and the other macros will cause an error if there is not at least one key. PUTMULTI uses ASSOC to match the keys.
The macros PUSHMULTI and PUSHMULTI-NEW are variations on this basic scheme.
(PUSHMULTI PLACE KEY1...KEYn VAL) [Macro]
(PUSHMULTI-NEW PLACE KEY1...KEYn VAL) [Macro]
PUSHMULTI pushes VAL at the front of the pair headed by KEYn, PUSHMULTI-NEW pushes VAL only if it is not already a MEMBER of the KEYn list. VAL is the value returned by both PUSHMULTI and PUSHMULTI-NEW.
Alternative and somewhat slower versions of these macros use SASSOC instead of ASSOC to traverse through the structure. All indexing keys are thus matched by EQUAL.
(SPUSHMULTI PLACE KEY1...KEYn VAL) [Macro]ÿÿ
ÿ(SPUTMULTI PLACE KEY1...KEYn VAL) [Macro]ÿÿ
ÿ(SPUSHMULTI-NEW PLACE KEY1...KEYn VAL) [Macro]
By way of illustration, the expression
(PUSHMULTI WINES 'RED 'DRY 'FRENCH 'CABERNET)
expands to the following code:
[LET ($$PAIR$$ $$KEY$$)ÿÿ
ÿ(LOCALVARS $$PAIR$$ $$KEY$$)ÿÿ
ÿ(SETQ $$KEY$$ 'RED)ÿÿ
ÿ(SETQ $$PAIR$$ (OR (ASSOC $$KEY$$ WINES)ÿÿ
ÿ (CAR (CL:PUSH (CONS $$KEY$$) WINES))))ÿÿ
ÿ(SETQ $$KEY$$ 'DRY)ÿÿ
ÿ(SETQ $$PAIR$$ (OR (ASSOC $$KEY$$ (CDR $$PAIR$$))ÿÿ
ÿ (CAR (CL:PUSH (CONS $$KEY$$) (CDR $$PAIR$$)))))ÿÿ
ÿ(SETQ $$KEY$$ 'FRENCH)ÿÿ
ÿ(SETQ $$PAIR$$ (OR (ASSOC $$KEY$$ (CDR $$PAIR$$))ÿÿ
ÿ (CAR (CL:PUSH (CONS $$KEY$$) (CDR $$PAIR$$)))))ÿÿ
ÿ(CAR (CL:PUSH 'CABERNET (CDR $$PAIR$$]
The keys of the PUT/PUSH macros are spread out as separate arguments. The macro STOREMULTI interprets a computed list of keys without requiring that they be spread into separate components.
(STOREMULTI PLACE KEYS VAL OPTIONS) [Macro]
Insures that there is a path from PLACE corresponding to the sequence of elements in the KEYS list. It then inserts VAL at the end of that path. SASSOC is used to match keys if OPTIONS is T or SASSOC or contains SASSOC, otherwise ASSOC is used. If options is or contains
PUSH: VAL is added to the list of items in the CDR of the last pair.
PUSHNEW: VAL is added if it is not already a MEMBER of the last-pair's list.
Otherwise, VAL replaces the CDR of the last pair. In any case the value is VAL.
The expressionÿÿ
ÿ (STOREMULTI \FONTSINCORE '(GACHA 10 (MEDIUM REGULAR REGULAR) 0 DISPLAY) FONT T)ÿÿ
ÿhas the same effect asÿÿ
ÿ (SPUTMULTI \FONTSINCORE 'GACHA 10 '(MEDIUM REGULAR REGULAR) 0 'DISPLAY FONT)ÿÿ
ÿbut is more convenient when the indexing parameters are provided as a FONTSPEC font-specification rather than a sequence of individual font attributes. (This uses the SASSOC option becauses font-faces are internalized as (weight slope expansion) lists.)
Retrieving values
The macro GETMULTI retrieves the value stored under a sequence of keys in a multi-alist:
(GETMULTI MULTIALIST KEY1...KEYn) [Macro]
Unlike the insertion macros, MULTIALIST for retrieval can be any arbitrarily computed value, not just something that CL:SETF can apply to.
The macro GETMULTI-PAIR behaves more like ASSOC: It produces the pair whose CAR is the key at the end of the specified path (e.g. (FRENCH PINOT-NOIR CABERNET)).
(GETMULTI-PAIR MULTIALIST KEY1...KEYn) [Macro]
Slow versions of these macros (using SASSOC instead of ASSOC) are also available:
(SGETMULTI MULTIALIST KEY1...KEYn VAL) [Macro]ÿÿ
ÿ(SGETMULTI-PAIR MULTIALIST KEY1...KEYn VAL) [Macro]
The expression (GETMULTI WINES 'RED 'DRY 'FRENCH) expands to
[CDR (ASSOC 'FRENCH (CDR (ASSOC 'DRY (CDR (ASSOC 'RED WINES]
The outer CDR in this expansion produces the value for the final key, and also means that the GETMULTI expression can be used as a commonLisp or Interlisp place in other expressions (e.g. CL:SETF, change, add).
(FETCHMULTI MULTIALIST KEYS SASSOC) [Macro]ÿÿ
ÿ(FETCHMULTI-PAIR MULTIALIST KEYS SASSOC) [Function]
Parallel to GETMULTI and GETMULTI-PAIR but with KEYS provided as a computed list. Keys match with SASSOC if SASSOC, otherwise ASSOC.
Removing values
Items can be removed from a multi-alist by the macros REMOVEMULTI and REMOVEMULTI-ALL:
(REMOVEMULTI MULTIALIST KEY1...KEYn VAL) [Macro]
Removes VAL from the location indexed by the keys (with REMOVE), essentially equivalent to
(change (GETMULTI MULTIALIST KEY1...KEYn) (REMOVE VAL DATUM))
(REMOVEMULTI-ALL MULTIALIST KEY1...KEYn) [Macro]
Removes all values at the location indexed by KEY1...KEYn, essentially equivalent to
(change (GETMULTI MULTIALIST KEY1...KEYn) NIL)
Other functions
(MAPMULTI MULTIALIST MAPFN) [Function]
The m-ary function MAPFN is applied to each m-length successive substructure of MULTIALIST. Thus, if F is a 4 argument function and (MAPMULTI WINES F) is evaluated, then on one application F will receive the arguments RED DRY FRENCH (PINOT-NOIR CABERNET). The arity m=4 in this case covers the 3 keys and the final value of each path. For m less than or equal to the number of keys, the last argument will be one entry in the trailing sub-alist of the structure after a prefix of initial keys. Thus for m=3 the function would receive
RED DRY (FRENCH PINOT-NOIR CABERNET)
at one of its applications.
(COLLECTMULTI MULTIALIST COLLECTFN) [Function]
This binds the special variable $$COLLECT, calls (MAPMULTI MULTIALIST COLLECTFN), and returns the final value of $$COLLECT. The result will thus contain any items that the mapping function decides to push onto $$COLLECT.
(EXTENDMULTI-PAIR MULTIALIST KEYS VAL OPTIONS) [Function]
MULTIALIST must be an alist with at least one pair. Insures that there is a path for KEYS descending from that alist, and that VAL is inserted in the last pair of that path. OPTIONS are as described above for STOREMULTI. For this function MULTIALIST must already exist, whereas STOREMULTI can create it from scratch and store at the location designated by its PLACE argument.
(SEQUENCE NIL NIL (0 0 0 0) ((PAGE NIL (PAPERSIZE Letter STARTINGPAGE# NIL LANDSCAPE? NIL FOLIOINFO (ARABIC "" "")) (0 0 612 792) ((HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (ALTERNATE NIL NIL (0 0 0 0) ((PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC)) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC)) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC)) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC)) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL)))))))
1$4È$È4È$È4È$È4$$È$È4È$È4$HÈ$È4È $È7$6È$È1È$1ŠŠ8$1ŠŠ8$JÈ$È PAGEHEADING RUNNINGHEAD/MODERN
(CHARPROPS (COLOR . BLACK))0CLASSIC
(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))/MODERN (CHARPROPS (COLOR . BLACK))/MODERNÿþ(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))1TERMINAL
(CHARPROPS (COLOR . BLACK))3
TIMESROMAN$(CHARPROPS (COLOR . BLACK))


 HRULE.GETFN  HRULE.GETFN  HRULE.GETFN   HRULE.GETFN  HRULE.GETFN
/  2C/@î-15#)%$,0v20 
A#%}K 



$+<§
     
'.  *)4242)¿

"2;X=
A =YVY


d¥
R  
==Ó
 
09W
Q  
.   
8
½%
;
 Ž

L&-;
o (((CHARENCODING . MCCS)))PROPS:#DATE:jŸ;k}zº