Viewing contents of file '../idllib/contrib/mallozzi/odoc.pro'
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
;+
; NAME:
;     oDoc
;
; PURPOSE:
;     Utility to parse object definition files and create HTML documentation
;     of the object methods.  Similar to, but less sophisticated than 
;     the java documentation facility 'javadoc'.
;
; CATEGORY:
;     Objects: documentation
;
; CALLING SEQUENCE:
;     oDoc [, objName]
;
; INPUTS:
;     objName (optional): STRING or STRARR denoting object(s) to parse.  
;     The array elements are the names of the objects; do not include
;     the "__define.pro" portion of the object file name.
;
;     If not supplied, objects are selected interactively from a list.
;
; KEYWORDS:
;     VERBOSE : Print information on the objects as they are parsed.
;
;     BGCOLOR : HTML color string denoting the background color for 
;               the HTML page           (DEFAULT = '#C0C0C0')
;     TEXT    : HTML text color         (DEFAULT = '#000000')
;     LINK    : HTML link color         (DEFAULT = '#0000E8')
;     ALINK   : HTML visited link color (DEFAULT = '#501888')
;
;     NOTE: Changing the background color from the default will not change
;           the background color of the bullet image that is used.  This is
;           due to a limitation of IDL's WRITE_GIF routine, which does not
;           preserve transparency in GIFs.  I suggest you use the default
;           colors.
;
; COMMON BLOCKS:
;     NONE
;
; SIDE EFFECTS:
;     None known.
;
; RESTRICTIONS:
;     None known.
;
; DEPENDENCIES:
;     dialog_list.pro
;     break_file.pro
;     write_image.pro (included)
;
; MODIFICATION HISTORY:
;     v0.11 : RSM, 1998 June
;         IF test error when selecting multiple objects
;         Added keywords to set the colors of the HTML:
;             BGCOLOR
;             TEXT
;             LINK
;             ALINK    
;         
;     v0.1  : Written, 1998 May, Robert.Mallozzi@msfc.nasa.gov
;
;-
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 



; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
;
; Writes a gif image used in the HTML
;
PRO WRITE_IMAGE

    image = BYTARR(12, 12)
    
    image[*, 0]  = [ 6,  6,  6, 84,  6,  6,   6, 84,  6,  6, 84,  6 ]
    image[*, 1]  = [ 6, 84,  6, 64, 90, 80,  80, 90, 93, 84,  6,  6 ]
    image[*, 2]  = [ 6,  6, 94, 95, 95, 80,  89, 89, 89, 96,  6,  6 ]
    image[*, 3]  = [ 6, 64, 75, 70, 75, 79,  91, 83, 92, 89, 93,  6 ]
    image[*, 4]  = [ 6, 56, 74, 74, 85, 87,  70, 79, 88, 89, 90, 84 ]
    image[*, 5]  = [ 6, 57, 81, 69, 81, 65,  82, 70, 79, 83, 80,  6 ]
    image[*, 6]  = [ 6, 57, 61, 68, 67, 77,  78, 74, 70, 79, 80,  6 ]
    image[*, 7]  = [ 6, 56, 60, 68, 71, 72,  73, 59, 74, 75, 76,  6 ]
    image[*, 8]  = [ 6, 64, 65, 60, 66, 67,  68, 69, 63, 70, 64,  6 ]
    image[*, 9]  = [ 6,  6, 58, 59, 60, 60,  61, 62, 63, 58,  6,  6 ]
    image[*, 10] = [ 6,  6,  6, 55, 56, 57,  57, 56, 55,  6,  6,  6 ]
    image[*, 11] = [ 6,  6,  6,  6,  6,  6,   6,  6,  6,  6,  6,  6 ]


    R = BYTARR (128)

    R[0:9]     = [ 255,   0, 194, 183, 102, 244, 191, 231, 111,  29 ] 
    R[10:19]   = [ 156,  86,   0,  63, 100, 194, 204, 206, 201, 214 ]
    R[20:29]   = [ 251, 231, 195, 198, 199, 255, 255, 251, 227, 151 ]
    R[30:39]   = [ 255, 255, 247, 189, 143, 130, 251, 207, 132,  87 ]
    R[40:49]   = [ 218, 175,  94, 196, 183, 167,  90,  74, 115, 113 ]
    R[50:59]   = [  69, 156, 206, 107, 137, 198, 206, 206, 206, 214 ]
    R[60:69]   = [ 255, 255, 239, 198, 198, 206, 255, 255, 255, 231 ]
    R[70:79]   = [ 156, 255, 255, 255, 189, 148, 132, 255, 214, 132 ]
    R[80:89]   = [ 90,  222, 181,  99, 198, 189, 255, 173,  90,  74 ]
    R[90:99]   = [ 115, 115,  74, 156, 206, 107, 140,   0,   0,   0 ]
    R[100:109] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    R[110:119] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    R[120:127] = [   0,   0,   0,   0,   0,   0,   0,   0 ]


    G = BYTARR (128)

    G[0:9]     = [ 255,   0, 194, 183, 102, 244, 191, 231, 111,  21 ]
    G[10:19]   = [ 156,  86,   0,  15, 100, 198, 206, 206, 206, 214 ]
    G[20:29]   = [ 255, 239, 198, 198, 206, 255, 252, 255, 231, 156 ]
    G[30:39]   = [ 234, 228, 255, 189, 148, 132, 255, 214, 132,  90 ]
    G[40:49]   = [ 222, 181,  99, 198, 189, 173,  89,  74, 115, 115 ]
    G[50:59]   = [  74, 156, 206, 107, 140, 123,  66,  16,  99,   0 ]
    G[60:69]   = [   0,   0,   0,   0, 123,   0,  16,  49,   8,   0 ]
    G[70:79]   = [   0, 140, 165,  16,   0,   0,  16,  33,   8,   0 ]
    G[80:89]   = [   0,   0,   0,   0, 189,   0, 255,   0,   0,   0 ]
    G[90:99]   = [  16,   0,   0,  74,  99,   0,  49,   0,   0,   0 ]
    G[100:109] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    G[110:119] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    G[120:127] = [   0,   0,   0,   0,   0,   0,   0,   0 ]


    B = BYTARR (128)

    B[0:9]     = [ 255,   0, 194, 183, 102, 244, 191, 231, 111,  91 ]
    B[10:19]   = [ 156,  86, 176, 123, 100, 123,  66,  16,  99,   0 ]
    B[20:29]   = [   0,   0,   0, 123,   0,  16,  49,   8,   0,   0 ]
    B[30:39]   = [ 140, 165,  16,   0,   0,  16,  33,   8,   0,   0 ]
    B[40:49]   = [   0,   0,   0, 189,   0,   0,   0,   0,  16,   0 ]
    B[50:59]   = [   0,  74,  99,   0,  49, 140, 107,  74, 123,  66 ]
    B[60:69]   = [  82,  74,  66,  57, 148,  57,  90, 123,  82,  66 ]
    B[70:79]   = [  41, 214, 239,  82,  57,  41,  49,  99,  66,  41 ]
    B[80:89]   = [  24,  66,  49,  24, 189,  49,   0,  49,  33,  24 ]
    B[90:99]   = [  49,  33,  16,  99, 132,  33,  74,   0,   0,   0 ]
    B[100:109] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    B[110:119] = [   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 ]
    B[120:127] = [   0,   0,   0,   0,   0,   0,   0,   0]

   
    WRITE_GIF, 'odoc-red-ball.gif', image, R, G, B
    

END
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PRO oDoc, objName, VERBOSE = verbose, $
    BGCOLOR = bgcolor, $
    TEXT = text, $
    LINK = link, $
    ALINK = alink
    
;     BGCOLOR : HTML color string denoting the backgroun color for 
;               the HTML page           (DEFAULT = '#C0C0C0')
;     TEXT    : HTML text color         (DEFAULT = '#000000')
;     LINK    : HTML link color         (DEFAULT = '#0000E8')
;     ALINK   : HTML visited link color (DEFAULT = '#501888')


    version = '0.11'
    

    verbose = KEYWORD_SET (verbose)    
    interactive = N_ELEMENTS (objName) EQ 0
    
    IF (N_ELEMENTS (bgcolor) EQ 0) THEN $
       bgcolor = '#C0C0C0'
       
    IF (N_ELEMENTS (text) EQ 0) THEN $
       text = '#000000'

    IF (N_ELEMENTS (link) EQ 0) THEN $
       link = '#0000E8'

    IF (N_ELEMENTS (alink) EQ 0) THEN $
       alink = '#501888'
    
    ; Object definition files
    ;
    objList = FINDFILE ('*__define.pro', COUNT = numObjs)
    IF (numObjs EQ 0) THEN BEGIN
       w = DIALOG_MESSAGE (/ERROR, 'No objects found.')
       RETURN
    ENDIF
    
    IF (NOT interactive) THEN BEGIN
    
       index = -1
       FOR i = 0, N_ELEMENTS (objName) - 1 DO BEGIN
           thisObj = objName[i]   
           j = WHERE (STRUPCASE (objList) EQ $
               STRUPCASE (thisObj + '__define.pro'), cnt)
           IF (cnt NE 0) THEN $
              index = [index, j] 
       ENDFOR
       IF (N_ELEMENTS (index) EQ 1) THEN BEGIN
          w = DIALOG_MESSAGE (/ERROR, 'No object definitions found.')
          RETURN
       ENDIF
       index = index[1:*]
       objList = objList[index]
       
       BREAK_FILE, objList, oDevList, oDirList, oNameList, oExtList    
       endPos = STRPOS (oNameList, '__define')
       todoList = STRARR (N_ELEMENTS (endPos))
       FOR i = 0, N_ELEMENTS (endPos) - 1 DO $
           todoList[i] = STRMID (oNameList[i], 0, endPos[i])
    
    ENDIF ELSE BEGIN
    
       BREAK_FILE, objList, oDevList, oDirList, oNameList, oExtList    
       endPos = STRPOS (oNameList, '__define')
       objNameList = STRARR (N_ELEMENTS (endPos))
       FOR i = 0, N_ELEMENTS (endPos) - 1 DO $
           objNameList[i] = STRMID (oNameList[i], 0, endPos[i])

       ySize = MAX ([MIN ([N_ELEMENTS (objNameList), 10]), 5])
       todoList = DIALOG_LIST (objNameList, /MULTIPLE, $
           TITLE = 'Select Objects', YSIZE = ysize)
       IF (todoList[0] EQ '') THEN $
          RETURN
    
    ENDELSE


    numObjs = N_ELEMENTS (todoList)

    FOR loop = 0, numObjs - 1 DO BEGIN
    
        objName = todoList[loop]
        haveMethods = 0 
        numMethods  = 0

        methodList = { $
            name:     '', $
            type:     '', $
            keywords: PTR_NEW(), $
            params:   PTR_NEW() $
        }
        method = methodList
                   
        filter   = STRTRIM (objName, 2) + '__*.pro'    
        objFiles = FINDFILE (filter, COUNT = numFiles)

        IF (verbose) THEN $
           MESSAGE, /CONTINUE, 'Parsing object "' + objName + '".'

        FOR j = 0, numFiles - 1 DO BEGIN

            currentFile = objFiles[j]

            ; Parse the object definition file, and extract methods
            ;
            line = ''
            OPENR, FL, currentFile, /GET_LUN
            WHILE (NOT EOF(FL)) DO BEGIN

                READF, FL, line

                ; Look for a header
		;
                startKey = ';+'
                endKey   = ';-'	
		IF (STRPOS (line, startKey) EQ 0) THEN BEGIN
		   header = line
		   REPEAT BEGIN
		       READF, FL, line
		       header = [header, line]
		   ENDREP UNTIL (STRPOS (line, endKey) EQ 0) 
                ENDIF
		
		index = -1

                IF (index EQ -1) THEN $
                   index = STRPOS(line, 'pro ')    

                IF (index EQ -1) THEN $
                   index = STRPOS(line, 'function ')    

                IF (index EQ -1) THEN $
                   index = STRPOS(line, 'PRO ')    

                IF (index EQ -1) THEN $
                   index = STRPOS(line, 'FUNCTION ')    

                ; Extract this line?
                ;
                IF (index NE -1) THEN BEGIN 

                   ; Remove embedded comments
                   ;
                   line = (STR_SEP (line[0], ';'))[0]

                   ; Add continued lines
                   ;
                   lineSave = line
                   WHILE (STRPOS(line, '$') NE -1) DO BEGIN
                       READF, FL, line
                       line = (STR_SEP (line[0], ';'))[0]
                       lineSave = [lineSave, line]
                   ENDWHILE

                   ; Extract the parameter list
                   ;                            
                   terms = STR_SEP (lineSave[0], ',')

                   ; Ensure it's a method, not a subroutine
                   ;               
                   isMethod = STRPOS(terms[0], '::')
                   IF (isMethod NE -1) THEN BEGIN
                      
                      haveMethods = 1

                      ; Remove line continuation character
                      ;
                      terms = terms (WHERE (STRCOMPRESS (terms, $
                          /REMOVE_ALL) NE '$'))

                      ; Current method name
                      ;
                      method.type = (STR_SEP (STRCOMPRESS(terms[0]), ' '))[0]
                      c = STRPOS (terms[0], '::')
                      method.name = STRMID (terms[0], c + 2, 999)

                      IF (verbose) THEN $
                         MESSAGE, /CONTINUE, '   Method: ' + method.name

                      ; Parameter list?
                      ;
                      IF (N_ELEMENTS (terms) GT 1) THEN BEGIN

                         ; Keywords
                         ;
                         k = WHERE (STRPOS (terms[1:*], '=') NE -1, cnt)
                         IF (cnt EQ 0) THEN BEGIN
                            method.keywords = PTR_NEW()
                         ENDIF ELSE BEGIN
                            method.keywords = PTR_NEW ((terms[1:*])[k])
                         ENDELSE

                         ; Parameters
                         ;
                         p = WHERE (STRPOS(terms[1:*], '=') EQ -1, cnt)
                         IF (cnt EQ 0) THEN BEGIN
                            method.params = PTR_NEW()
                         ENDIF ELSE BEGIN
                            method.params = PTR_NEW ((terms[1:*])[p])
                         ENDELSE

                      ENDIF ELSE BEGIN

                         method.keywords = PTR_NEW()
                         method.params   = PTR_NEW()

                      ENDELSE

                      ; Store this method
                      ;
                      methodList = [methodList, method] 

                   ENDIF ; isMethod

                ENDIF ; index  

            ENDWHILE ; NOT EOF
            FREE_LUN, FL

        ENDFOR ; numFiles


        ; Object may have no methods
        ; 
        IF (haveMethods) THEN BEGIN
           
           ; Alphabetize by method name
           ; 
           methodList = methodList[1:*]        
           methodList = methodList (SORT (methodList.name))
           numMethods = N_ELEMENTS(methodList)
        
        ENDIF ELSE BEGIN
        
           numMethods = 0
         
        ENDELSE

        IF (verbose) THEN $
           MESSAGE, /CONTINUE, 'Object "' + objName + '", ' + $
               STRTRIM (numMethods, 2) + ' methods.'

        ; Write the html for this object
        ;
        WRITE_IMAGE

        outFile = objName + '.html'        
        OPENW, FL, outFile, /GET_LUN
        S = [ $
            '<HTML>', $
            '<HEAD>', $
            '<TITLE>' + 'Class ' + objName + '</TITLE>', $
            '</HEAD>', $
            '<BODY ' + $
                'BGCOLOR = "' + bgcolor + '" ' + $
		'TEXT = "' + text + '" ' + $
		'LINK = "' + link + '" ' + $
		'ALINK = "' + alink + '">' $
        ]

        FOR i = 0, N_ELEMENTS(S) - 1 DO $
            PRINTF, FL, S[i]

        PRINTF, FL, '<HR>'
        PRINTF, FL, '<H2 ALIGN = "center"> Class ' + objName + '</H2>'
        PRINTF, FL, '<HR>'
         
        IF (N_ELEMENTS (header) NE 0) THEN BEGIN
	   PRINTF, FL, '<PRE>'
           FOR i = 0, N_ELEMENTS (header) - 1 DO $
	       PRINTF, FL, header[i]
	   PRINTF, FL, '</PRE>'
           PRINTF, FL, '<HR>'
        ENDIF
	
        IF (numMethods NE 0) THEN $
           PRINTF, FL, '<P><B>Object Methods</B></P>'
        FOR i = 0, numMethods - 1 DO BEGIN
            method = methodList[i]
            anchor = '<P><A HREF = "#' + method.name + '">' + method.name
            PRINTF, FL, anchor + '</A></P>'
        ENDFOR

        PRINTF, FL, '<HR>'

        ; Now each method with parameters
        ;
        FOR i = 0, numMethods - 1 DO BEGIN

            method = methodList[i]

            anchor = '<A NAME = "' + method.name + '">'
            image  = '<IMG SRC = "odoc-red-ball.gif">'
            PRINTF, FL, '<P>' + image + anchor + $
                ' <B>' + method.name + '</B></A>'

            PRINTF, FL, '<BR><EM>Type:</EM> ' + method.type + '<BR>'

            IF (PTR_VALID (method.keywords)) THEN BEGIN

               PRINTF, FL, '<EM>Keywords:</EM>'
               PRINTF, FL, '<PRE>'
               FOR j = 0, N_ELEMENTS(*method.keywords) - 1 DO $
                   PRINTF, FL, '   ' + (*method.keywords)[j]
               PRINTF, FL, '</PRE>'

            ENDIF ELSE BEGIN

               PRINTF, FL, '<EM>Keywords:</EM> No Keywords<BR>'

            ENDELSE

            IF (PTR_VALID (method.params)) THEN BEGIN

               PRINTF, FL, '<EM>Parameters:</EM>'
               PRINTF, FL, '<PRE>'
               FOR j = 0, N_ELEMENTS(*method.params) - 1 DO $
                   PRINTF, FL, '   ' + (*method.params)[j]
               PRINTF, FL, '</PRE>'

            ENDIF ELSE BEGIN

               PRINTF, FL, '<EM>Parameters:</EM> No Parameters'

            ENDELSE

        ENDFOR

        PRINTF, FL, '<HR>'
        PRINTF, FL, '<P>oDoc v' + version
        FREE_LUN, FL
        
        ; Cleanup
        ;
        FOR i = 0, N_ELEMENTS (methodList) - 1 DO BEGIN
            PTR_FREE, methodList[i].keywords
            PTR_FREE, methodList[i].params
        ENDFOR    

    ENDFOR ; k
        


             
END