home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / SML⁄NJ 93+ / Documentation / examples / picture.sml < prev    next >
Encoding:
Text File  |  1995-12-30  |  3.2 KB  |  96 lines  |  [TEXT/R*ch]

  1. (* picture.sml *)
  2.  
  3. (* Picture example based on Andy Koenig's columns on "Analysis of a
  4.    classroom exercise" (Parts 1-3).
  5.  
  6.    The abstraction implements two-dimensional character pictures that
  7.    can be framed, composed horizontally and vertically, and printed. *)
  8.  
  9. signature PICTURE =
  10. sig
  11.   type picture
  12.   val picture : string list -> picture
  13.        (* the strings in the argument form successive rows of the picture *)
  14.   val frame : picture -> picture
  15.        (* add a frame around the picture *)
  16.   val hcat : picture * picture -> picture
  17.        (* concatenate two pictures horizontally, alligning tops *)
  18.   val vcat : picture * picture -> picture
  19.        (* concatenate two pictures vertically, alligning left edges *)
  20.   val width : picture -> int
  21.        (* return the width of a picture in characters *)
  22.   val height : picture -> int
  23.        (* return the height of a picture in characters *)
  24.   val display : outstream -> picture -> unit
  25.        (* print a two-dimensional representation of the picture on the
  26.       given outstream *)
  27. end
  28.  
  29. abstraction Picture: PICTURE =  (* Picture.picture is an abstract type *)
  30. struct
  31.  
  32.   datatype contents
  33.     = ROWS of string list
  34.     | FRAME of picture
  35.     | HCAT of picture * picture
  36.     | VCAT of picture * picture
  37.   withtype picture = {cont: contents, width: int, height: int}
  38.  
  39.   fun picture(rows: string list) =
  40.       {cont = ROWS rows,
  41.        width = fold (fn (s,m) => max(m, size s)) rows 0,
  42.        height = length rows}
  43.  
  44.   fun frame (p as {cont,width,height}: picture) =
  45.       {cont = FRAME p, width = width + 2, height = height + 2}
  46.  
  47.   fun hcat(p1 as {width = w1, height = h1,...}: picture,
  48.        p2 as {width = w2, height = h2,...}: picture) = 
  49.       {cont = HCAT(p1,p2), width = w1+w2, height = max(h1,h2)}
  50.  
  51.   fun vcat(p1 as {width = w1, height = h1,...}: picture,
  52.        p2 as {width = w2, height = h2,...}: picture) = 
  53.       {cont = VCAT(p1,p2), width = max(w1,w2), height = h1+h2}
  54.  
  55.   fun width({width,...}: picture) = width
  56.   fun height({height,...}: picture) = height
  57.  
  58.   fun display (os: outstream) (p as {width = wd, height = ht,...}: picture) =
  59.       let val pr = outputc os
  60.       fun pad(ch,n) =
  61.           let fun for(0) = ()
  62.             | for(i) = (pr ch; for(i-1))
  63.            in for n
  64.           end
  65.       fun display_row({cont,width=w,height=h},row,row_width) =
  66.           case cont
  67.         of ROWS rows =>
  68.             (let val r = nth(rows,row)
  69.               in pr r; pad(" ", row_width - size r)
  70.              end
  71.              handle Nth => pad(" ", row_width))
  72.              | FRAME p =>
  73.              if row < 0 orelse row >= h
  74.              then pad(" ",row_width)
  75.              else (if row = 0 orelse row = h-1
  76.                    then (pr "+"; pad("-",width(p)); pr "+")
  77.                    else (pr "|"; display_row(p,row-1,width(p)); pr "|");
  78.                pad(" ", row_width - w))
  79.              | HCAT(left,right) =>
  80.             (display_row(left,row,width(left));
  81.              display_row(right,row,width(right));
  82.              pad(" ",row_width-w))
  83.          | VCAT(top,bottom) =>
  84.              if row >= 0 andalso row < height(top)
  85.              then display_row(top,row,row_width)
  86.              else if row >= height(top) andalso row < h
  87.              then display_row(bottom,row-height(top),row_width)
  88.              else pad(" ",row_width)
  89.       fun scan row =
  90.           if row >= ht then ()
  91.           else (display_row(p,row,wd); pr "\n"; scan(row+1))
  92.        in scan 0
  93.       end
  94.  
  95. end (* structure Picture *)
  96.