(FILECREATED "23-Jan-86 14:26:21" {ERIS}<CUTTING>LISP>XQPM.;28 23757  

      changes to:  (FNS XQPM.CREF XQPM.UPDATE.FROM.CREF XQPM.CREF.TO.ID XQPM.HELP XQPM.MANUAL)

      previous date: "21-Jan-86 20:07:22" {ERIS}<CUTTING>LISP>XQPM.;26)


(* Copyright (c) 1985, 1986 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT XQPMCOMS)

(RPAQQ XQPMCOMS ((FILES DINFO)
                 (RECORDS XQPMREF)
                 [COMS (* Runtime code)
                       (FNS (* called from prolog)
                            XQPM.HELP XQPM.MANUAL)
                       (FNS (* called from lisp)
                            XQPM.GET.GRAPH XQPM.CREF XQPM.UPDATE.FROM.CREF XQPM.CREF.TO.ID 
                            XQPM.LOOKUP XQPM.BSEARCH XQPM.CHOOSE.REF XQPM.GATHER.REFS \XQPM.RESET)
                       (MACROS XQPM.SUBSTRINGP)
                       (INITVARS (PROLOGHELPDIRECTORY)
                              (XQPM.FONT (FONTCREATE (QUOTE TERMINAL)
                                                10)))
                       (GLOBALVARS PROLOGHELPDIRECTORY XQPM.FONT)
                       (ADDVARS (DINFO.GRAPHS ("Xerox Quintus Prolog Manual" (XQPM.GET.GRAPH T]
                 (COMS (* MAKESYS time code)
                       (FNS XQPM.SETUP XQPM.MAKEINDEX XQPM.MAKEGRAPH XQPM.MAKE.NODE 
                            XQPM.GET.PARENT.ID)
                       (INITVARS (\XQPM.INDEX.ARRAY)
                              (\XQPM.DINFO.GRAPH))
                       (GLOBALVARS \XQPM.INDEX.ARRAY \XQPM.DINFO.GRAPH))))
(FILESLOAD DINFO)
[DECLARE: EVAL@COMPILE 

(DATATYPE XQPMREF (ITEM TYPE NODEID))
]
(/DECLAREDATATYPE (QUOTE XQPMREF)
       (QUOTE (POINTER POINTER POINTER))
       (QUOTE ((XQPMREF 0 POINTER)
               (XQPMREF 2 POINTER)
               (XQPMREF 4 POINTER)))
       (QUOTE 6))



(* Runtime code)

(DEFINEQ

(XQPM.HELP
  [LAMBDA (ATOM)                                                          (* drc: 
                                                                          "23-Jan-86 14:06")
            
            (* * Lookup ATOM in the index of the online manual.
            Called by prolog predicate "help(Topic)")

    (LET ((GRAPH (XQPM.GET.GRAPH)))
         (RESETFORM (TTYDISPLAYSTREAM (GETPROMPTWINDOW (fetch (DINFOGRAPH WINDOW) of GRAPH)))
                (XQPM.LOOKUP (MKSTRING ATOM)
                       GRAPH))
     NIL])

(XQPM.MANUAL
  [LAMBDA (SECTION)                                                       (* drc: 
                                                                          "23-Jan-86 14:06")
            
            (* * Visit SECTION of the online manual.
            Called by prolog predicate "manual(Section)")

    (LET ((GRAPH (XQPM.GET.GRAPH)))
         (RESETFORM (TTYDISPLAYSTREAM (GETPROMPTWINDOW (fetch (DINFOGRAPH WINDOW) of GRAPH)))
                (XQPM.UPDATE.FROM.CREF (MKSTRING SECTION)
                       GRAPH))
     NIL])
)
(DEFINEQ

(XQPM.GET.GRAPH
  [LAMBDA (FROMBACKGROUND?)                                               (* drc: 
                                                                          "21-Jan-86 19:46")
            
            (* * Returns the DInfo graph for the XQPM, initializing if necesary.)

    (DECLARE (GLOBALVARS PROLOGHELPDIRECTORY \XQPM.DINFO.GRAPH))          (* drc: 
                                                                          "19-Dec-85 17:47")
    (if (AND (type? DINFOGRAPH \XQPM.DINFO.GRAPH)
             (WINDOWP (fetch (DINFOGRAPH WINDOW) of \XQPM.DINFO.GRAPH)))
        then \XQPM.DINFO.GRAPH
      elseif (INFILEP (PACKFILENAME (QUOTE NAME)
                             (QUOTE R0101)
                             (QUOTE BODY)
                             PROLOGHELPDIRECTORY))
        then (OR (type? DINFOGRAPH \XQPM.DINFO.GRAPH)
                 (ERROR "XQPM DInfo graph not installed!" "Try (XQPM.SETUP >>HOST&DIR<<)."))
             (replace (DINFOGRAPH DEFAULTHOST) of \XQPM.DINFO.GRAPH with (FILENAMEFIELD 
                                                                                PROLOGHELPDIRECTORY
                                                                                (QUOTE HOST)))
             (replace (DINFOGRAPH DEFAULTDEVICE) of \XQPM.DINFO.GRAPH with (FILENAMEFIELD
                                                                            PROLOGHELPDIRECTORY
                                                                            (QUOTE DEVICE)))
             (replace (DINFOGRAPH DEFAULTDIR) of \XQPM.DINFO.GRAPH with (FILENAMEFIELD 
                                                                               PROLOGHELPDIRECTORY
                                                                               (QUOTE DIRECTORY)))
             (replace (DINFOGRAPH TEXTPROPS) of \XQPM.DINFO.GRAPH with (LIST (QUOTE FONT)
                                                                             XQPM.FONT))
             (replace (DINFOGRAPH MENUFONT) of \XQPM.DINFO.GRAPH with XQPM.FONT)
             (replace (DINFOGRAPH WINDOW) of \XQPM.DINFO.GRAPH
                with (CREATEW (GETBOXREGION 500 300 NIL NIL NIL "Specify region for XQPM DInfo Graph"
                                     )
                            "XQPM DInfo Graph"))
             (OR FROMBACKGROUND? (DINFO \XQPM.DINFO.GRAPH NIL T T))
             \XQPM.DINFO.GRAPH
      else (ERROR "Set PROLOGHELPDIRECTORY to the location of the manual files.")
           NIL])

(XQPM.CREF
  [LAMBDA (ITEM FM.WINDOW BUTTONS)                                        (* drc: 
                                                                          "23-Jan-86 14:16")
    (LET*((GRAPH (DINFOGRAPH FM.WINDOW))
          (W (fetch (DINFOGRAPH WINDOW) of GRAPH))
          (TEXTSTREAM (WINDOWPROP W (QUOTE TEXTSTREAM)))
          (TEXTOBJ (TEXTOBJ TEXTSTREAM))
          CREF SEL)
     (RESETFORM (TTYDISPLAYSTREAM (GETPROMPTWINDOW W))
            (CLEARW T)
            (SELECTQ (FM.ITEMPROP ITEM (QUOTE ID))
                (GOTOREF (SETQ SEL (TEDIT.SEL.AS.STRING TEXTSTREAM (TEDIT.GETSEL TEXTSTREAM)))
                         (if (AND (STRING-EQUAL (SUBSTRING SEL 1 8)
                                         "{manual(")
                                  (STRING-EQUAL (SUBSTRING SEL -2)
                                         ")}"))
                             then (XQPM.UPDATE.FROM.CREF (SUBSTRING SEL 9 -3)
                                         GRAPH)
                           else (PRINTOUT T T "No cross reference selected.  Try NextRef!")))
                (NEXTREF (PRINTOUT T "Searching...")
                         (SETQ CREF (TEDIT.FIND TEXTOBJ "{manual(*)}" NIL NIL T))
                         (if CREF
                             then (TEDIT.NORMALIZECARET TEXTOBJ (SETQ SEL
                                                                 (TEDIT.SETSEL
                                                                  TEXTSTREAM
                                                                  (CAR CREF)
                                                                  (ADD1 (IDIFFERENCE (CADR CREF)
                                                                               (CAR CREF)))
                                                                  (QUOTE RIGHT)
                                                                  T)))
                                  (PRINTOUT T T "OK.  Select GoToRef! to go to "
                                         (SUBSTRING (TEDIT.SEL.AS.STRING TEXTSTREAM SEL)
                                                2 -2)
                                         ".")
                           else (PRINTOUT T T "No more cross references in this node")
                                (TEDIT.NORMALIZECARET TEXTOBJ (TEDIT.SETSEL TEXTSTREAM 0 0))))
                (SHOULDNT])

(XQPM.UPDATE.FROM.CREF
  [LAMBDA (STRING GRAPH)                                                  (* drc: 
                                                                          "23-Jan-86 14:24")
            
            (* Go to node in GRAPH denoted by STRING.
            STRING should be a string encoding the nodeid of the cross referenced 
            node, where "ref-1-11" encodes nodeid R0111.)

    (LET*[(ID (XQPM.CREF.TO.ID STRING))
          (NODE (FASSOC ID (fetch (DINFOGRAPH NODELST) of GRAPH]
     (if NODE
         then (DINFO.UPDATE GRAPH NODE)
       else (printout T T "Section " STRING " not found."])

(XQPM.CREF.TO.ID
  [LAMBDA (CREF)                                                          (* drc: 
                                                                          "23-Jan-86 14:24")
            
            (* * converts a ref-1-2 style cross reference
            (CREF) to a R0102 style ID.)

    (LET ((L (UNPACK CREF)))
         (PACK (CONS (U-CASE (CAR L))
                     (for TAIL on L bind FLG
                        join (if (SMALLP (CAR TAIL))
                                 then (if FLG
                                          then (SETQ FLG)
                                               (LIST (CAR TAIL))
                                        elseif (SMALLP (CADR TAIL))
                                          then (SETQ FLG T)
                                               (LIST (CAR TAIL))
                                        else (LIST 0 (CAR TAIL)))
                               else NIL])

(XQPM.LOOKUP
  [LAMBDA (STRING GRAPH)                                                  (* drc: 
                                                                          "15-Jan-86 23:11")
            
            (* LOOKUPFN for XQPM DInfo graph. All index entries for which STRING is an 
            initial substring of are gathered and put in the manual for the user to 
            select which one to lookup.)

    (LET*[(W (fetch (DINFOGRAPH WINDOW) of GRAPH))
          [SAME? (STRING-EQUAL STRING (WINDOWPROP W (QUOTE XQPM.LAST.LOOKUP]
          (REFS (if SAME?
                    then (WINDOWPROP W (QUOTE XQPM.LAST.REFS))
                  else (XQPM.BSEARCH (L-CASE STRING]
     (WINDOWPROP W (QUOTE XQPM.LAST.LOOKUP)
            STRING)
     (WINDOWPROP W (QUOTE XQPM.LAST.REFS)
            REFS)
     (if REFS
         then [LET ((REF (XQPM.CHOOSE.REF REFS W SAME?)))
                   (AND REF (DINFO.UPDATE GRAPH (FASSOC (fetch (XQPMREF NODEID) of REF)
                                                       (fetch (DINFOGRAPH NODELST) of GRAPH))
                                   (MKSTRING (fetch (XQPMREF ITEM) of REF]
       else (PRINTOUT T T STRING " not found in index"])

(XQPM.BSEARCH
  [LAMBDA (ITEM)                                                          (* drc: 
                                                                          "15-Jan-86 23:15")
            
            (* * returns the list of XQPMREF's in \XQPM.INDEX.ARRAY whose ITEM fields' 
            initial substrings match ITEM. Binary searches until it finds a match, 
            then gathers all the matches neighboring it.
            Algorithm courtesy of Knuth, Volume 3, Sorting and Searching, page 407)

    (RESETFORM (CURSOR WAITINGCURSOR)
           (PROG ((ARRAY (GETTOPVAL (QUOTE \XQPM.INDEX.ARRAY)))
                  (ITEMLEN (NCHARS ITEM))
                  (L 1)
                  U I REF FLG)
                 (SETQ U (ARRAYSIZE ARRAY))
             LOOP
                 (if (LESSP U L)
                     then (RETURN NIL))
                 (SETQ I (IQUOTIENT (IPLUS L U)
                                2))
                 (SETQ REF (ELT ARRAY I))
                 (SETQ FLG (ALPHORDER ITEM (fetch (XQPMREF ITEM) of REF)))
                 (if (NULL FLG)
                     then (SETQ L (ADD1 I))
                          (GO LOOP)
                   elseif (OR (EQ FLG (QUOTE EQUAL))
                              (XQPM.SUBSTRINGP ITEM ITEMLEN (fetch (XQPMREF ITEM) of REF)))
                     then (RETURN (XQPM.GATHER.REFS ITEM ITEMLEN REF I ARRAY))
                   else (SETQ U (SUB1 I))
                        (GO LOOP])

(XQPM.CHOOSE.REF
  [LAMBDA (REFS W SAME?)                                                  (* drc: 
                                                                          "15-Jan-86 23:11")
    (if (NULL (CDR REFS))
        then (CAR REFS)
      else (LET [(MENU (if SAME?
                           then (WINDOWPROP W (QUOTE XQPM.LOOKUP.MENU))
                         else (create MENU
                                     CENTERFLG ← T
                                     TITLE ← STRING
                                     ITEMS ←(for REF in REFS collect (LIST (fetch (XQPMREF TYPE)
                                                                              of REF)
                                                                           REF]
                (WINDOWPROP W (QUOTE XQPM.LOOKUP.MENU)
                       MENU)
                (MENU MENU])

(XQPM.GATHER.REFS
  [LAMBDA (ITEM ITEMLEN REF POINT ARRAY)                                  (* drc: 
                                                                          "18-Dec-85 18:57")
            
            (* Assumes that REF (which is at POINT in ARRAY) matches ITEM, and 
            collects the references on either side of REF which also match ITEM.
            As we are matching ITEM with initial substring's of the ITEM fields of the 
            XQPMREF's in ARRAY, and we know that ARRAY is sorted alphabetically by 
            this field, we can be sure that all matches will be adjacent.)

    (LET ((BEFORE (for I from (SUB1 POINT) to 1 by -1 bind REF eachtime (AND (GEQ I 1)
                                                                             (SETQ REF
                                                                              (ELT ARRAY I)))
                     while (XQPM.SUBSTRINGP ITEM ITEMLEN (fetch (XQPMREF ITEM) of REF)) collect
                                                                                        REF))
          (AFTER (for I from (ADD1 POINT) to (ARRAYSIZE ARRAY) bind REF
                    eachtime (AND (LEQ I (ARRAYSIZE ARRAY))
                                  (SETQ REF (ELT ARRAY I))) while (XQPM.SUBSTRINGP
                                                                   ITEM ITEMLEN (fetch (XQPMREF
                                                                                        ITEM)
                                                                                   of REF))
                    collect REF)))
         (NCONC (DREVERSE BEFORE)
                (LIST REF)
                AFTER])

(\XQPM.RESET
  [LAMBDA NIL                                                             (* drc: 
                                                                          "16-Jan-86 15:25")
    (if (type? DINFOGRAPH \XQPM.DINFO.GRAPH)
        then (LET ((W (fetch (DINFOGRAPH WINDOW) of \XQPM.DINFO.GRAPH)))
                  (OPENW W)
                  (CLOSEW W)))
    (SETQ PROLOGHELPDIRECTORY)
    (SETQ \XQPM.DINFO.GRAPH)
    (SETQ \XQPM.INDEX.ARRAY])
)
(DECLARE: EVAL@COMPILE 
[PUTPROPS XQPM.SUBSTRINGP MACRO ((X XLEN Y)
                                 (STREQUAL X (SUBSTRING Y 1 XLEN]
)

(RPAQ? PROLOGHELPDIRECTORY )

(RPAQ? XQPM.FONT (FONTCREATE (QUOTE TERMINAL)
                        10))
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS PROLOGHELPDIRECTORY XQPM.FONT)
)

(ADDTOVAR DINFO.GRAPHS ("Xerox Quintus Prolog Manual" (XQPM.GET.GRAPH T)))



(* MAKESYS time code)

(DEFINEQ

(XQPM.SETUP
  [LAMBDA (HOST&DIR)                                                      (* drc: 
                                                                          "16-Jan-86 15:23")
            
            (* * Sets up the XQPM. To be called when assembling a prolog sysout.
            HOST&DIR should be the prolog sources directory and should contain files 
            XQPM.FILETITLES and XQPM.INDEX.)

    (XQPM.MAKEGRAPH HOST&DIR)
    (XQPM.MAKEINDEX HOST&DIR])

(XQPM.MAKEINDEX
  [LAMBDA (HOST&DIR)                                                      (* drc: 
                                                                          "16-Jan-86 21:20")
            
            (* * Reads the file named XQPM.INDEX on HOST&DIR sorts its contents, and 
            makes \XQPM.INDEX.ARRAY out of it. File should contain a sequence of
            (ItemAtom TypeString NodeID) where NodeID is the name of the file
            (and the nodeid of the node) containing the reference to ItemAtom as a 
            TypeString.)

    (DECLARE (GLOBALVARS \XQPM.INDEX.ARRAY))
    (PRINTOUT T "Making index array...")
    (PRINTOUT T "reading...")
    (LET*((ENTRIES (READFILE (PACKFILENAME (QUOTE NAME)
                                    (QUOTE XQPM.INDEX)
                                    (QUOTE BODY)
                                    HOST&DIR)))
          (#ENTRIES (FLENGTH ENTRIES)))
     [MAP ENTRIES (FUNCTION (LAMBDA (TAIL)
                              (RPLACA TAIL (L-CASE (CAR TAIL]             (* L-CASE the ITEM 
                                                                          fields before sorting)
     (PRINTOUT T "sorting...")
     [SORT ENTRIES (FUNCTION (LAMBDA (A B)
                               (ALPHORDER (CAR A)
                                      (CAR B]
     (SETQ \XQPM.INDEX.ARRAY (ARRAY #ENTRIES))
     (printout T "inserting...")
     [for ENTRY in ENTRIES as I from 1 to #ENTRIES do (SETA \XQPM.INDEX.ARRAY I
                                                            (create XQPMREF
                                                                   ITEM ←(CAR ENTRY)
                                                                   TYPE ←(CADR ENTRY)
                                                                   NODEID ←(U-CASE (CADDR ENTRY]
     (printout T "OK." T])

(XQPM.MAKEGRAPH
  [LAMBDA (HOST&DIR)                                                      (* drc: 
                                                                          "21-Jan-86 19:57")
            
            (* Expects HOST&DIR to contain a file called XQPM.FILETITLES which 
            contains a sequence of (filename/nodeid nodename fileexists?) lists, where 
            filename/nodeid is both (possibly) the name of a documentation file, and 
            an encoded graph position. Encoding of reference manual section 4-12-2 
            would be R041202. The file is expected to be ordered in the order the 
            corresponding sections of the manual occur in.)

    (DECLARE (GLOBALVARS \XQPM.DINFO.GRAPH))
    (PRINTOUT T "Making DInfo graph...")
    (PRINTOUT T "reading...")
    (LET*((FILETITLES (READFILE (PACKFILENAME (QUOTE NAME)
                                       (QUOTE XQPM.FILETITLES)
                                       (QUOTE BODY)
                                       HOST&DIR)))
          (TOPNODE (create DINFONODE
                          ID ←(CAAR FILETITLES)
                          LABEL ←(CADAR FILETITLES)))
          (NODELST (LIST TOPNODE)))
     [SETQ \XQPM.DINFO.GRAPH (create DINFOGRAPH
                                    NAME ←"XQPM"
                                    TOPNODEID ←(fetch (DINFONODE ID) of TOPNODE)
                                    LOOKUPFN ←(FUNCTION XQPM.LOOKUP)
                                    FREEMENUITEMS ←(QUOTE ((ID NEXTREF LABEL "NextRef!" SELECTEDFN 
                                                               XQPM.CREF FONT (HELVETICA 10 BOLD)
                                                               MESSAGE 
                                                             "Find next cross reference in this node"
                                                               )
                                                           (ID GOTOREF LABEL "GoToRef!" SELECTEDFN 
                                                               XQPM.CREF FONT (HELVETICA 10 BOLD)
                                                               MESSAGE 
                                                           "Go to currently selected cross reference"
                                                               ]
     (PRINTOUT T "creating NODELST...")                                   (* chug through the 
                                                                          nodes...)
     (for X in (CDR FILETITLES) do (XQPM.MAKE.NODE (CAR X)
                                          (CADR X)
                                          (CADDR X)
                                          NODELST HOST&DIR))
     (replace (DINFOGRAPH NODELST) of \XQPM.DINFO.GRAPH with NODELST)
     (PRINTOUT T "OK." T])

(XQPM.MAKE.NODE
  [LAMBDA (ID LABEL FILE? NODELST HOST&DIR)                               (* drc: 
                                                                          "21-Jan-86 20:00")
            
            (* * Takes filename/nodeid ID, and node label LABEL, creates a DINFONODE 
            for them, and inserts it into NODELST appropriatly.
            FILE? is T if there really is a file (named ID) for the node.)

    (if (AND (EQ (MKATOM (SUBSTRING ID -2))
                 0)
             (STRING-EQUAL LABEL "Overview"))
        then                                                              (* zeroth sections named 
                                                                          "Overview" don't get 
                                                                          turned into nodes --
                                                                          their text is just slid 
                                                                          up into their textless 
                                                                          parent.)
             (replace (DINFONODE FILE) of (FASSOC (XQPM.GET.PARENT.ID ID NODELST)
                                                 NODELST) with ID)
      else (LET ((PREVIOUS (CAR NODELST))
                 NODE)
                (replace (DINFONODE NEXTNODE) of PREVIOUS with ID)
                [LET*((PARENTID (XQPM.GET.PARENT.ID ID NODELST))
                      (PARENT (FASSOC PARENTID NODELST)))
                 (replace (DINFONODE CHILDREN) of PARENT with (ATTACH ID (fetch (DINFONODE CHILDREN)
                                                                            of PARENT)))
                 (SETQ NODE (create DINFONODE
                                   LABEL ← LABEL
                                   FILE ←(AND FILE? ID)
                                   ID ← ID
                                   PARENT ← PARENTID
                                   PREVIOUSNODE ←(fetch (DINFONODE ID) of PREVIOUS]
                (ATTACH NODE NODELST])

(XQPM.GET.PARENT.ID
  [LAMBDA (ID NODELST)                                                    (* drc: 
                                                                          "18-Dec-85 19:11")
            
            (* * Decodes the ID of the node whose ID is ID and returns the ID of its 
            Parent node.)

    (if (EQ (NCHARS ID)
            1)
        then                                                              (* Parent is top node, 
                                                                          which should be last in 
                                                                          nodelst.)
             (fetch (DINFONODE ID) of (CAR (FLAST NODELST)))
      else (MKATOM (SUBSTRING (MKSTRING ID)
                          1 -3])
)

(RPAQ? \XQPM.INDEX.ARRAY )

(RPAQ? \XQPM.DINFO.GRAPH )
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \XQPM.INDEX.ARRAY \XQPM.DINFO.GRAPH)
)
(PUTPROPS XQPM COPYRIGHT ("Xerox Corporation" 1985 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1840 2932 (XQPM.HELP 1850 . 2385) (XQPM.MANUAL 2387 . 2930)) (2933 15082 (
XQPM.GET.GRAPH 2943 . 5452) (XQPM.CREF 5454 . 7826) (XQPM.UPDATE.FROM.CREF 7828 . 8454) (
XQPM.CREF.TO.ID 8456 . 9396) (XQPM.LOOKUP 9398 . 10594) (XQPM.BSEARCH 10596 . 12060) (XQPM.CHOOSE.REF 
12062 . 12931) (XQPM.GATHER.REFS 12933 . 14623) (\XQPM.RESET 14625 . 15080)) (15507 23535 (XQPM.SETUP 
15517 . 15991) (XQPM.MAKEINDEX 15993 . 17851) (XQPM.MAKEGRAPH 17853 . 20675) (XQPM.MAKE.NODE 20677 . 
22752) (XQPM.GET.PARENT.ID 22754 . 23533)))))
STOP