home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 283.lha / DMouse_v1.20 / src / dlineart.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-07  |  13.4 KB  |  696 lines

  1.  
  2. /*
  3.  *  DLineArt.c
  4.  *
  5.  *  DMouse screen blanker for use with DMouse V1.20
  6.  *
  7.  *  read the docs file for installation procedures.
  8.  *
  9.  *  Is your computer BORED? If so, then you need...
  10.  *
  11.  *        DLineArt, by Steve -Raz- Berry with help
  12.  *        from Matt Dillon.
  13.  *
  14.  *  Compile +L w/ sup32.lib.  libs:dres.library no longer required
  15.  */
  16.  
  17. #include <local/typedefs.h>
  18. #include <local/ipc.h>
  19. #include <local/xmisc.h>
  20.  
  21. typedef struct IORequest IORequest;
  22.  
  23. #define MAXELLIPSE 75
  24.  
  25. /* Be carefule if modifiying the following defines... */
  26.  
  27. int MAXX, MAXY;
  28.  
  29. #define MINBOUND 20
  30. #define BOUNDX MAXX-MINBOUND
  31. #define BOUNDY MAXY-MINBOUND
  32.  
  33. #define TEXTSTR 0x10
  34. #define SPLINES 0x8
  35. #define LINES 0x4
  36. #define BOXES 0x2
  37. #define ELLIPSES 0x1
  38.  
  39. /* Maximun # of lines,boxes,ellipses to draw (watch your stack!) */
  40.  
  41. #define MAXLINES 500
  42.  
  43. UWORD coltbl[2] = {
  44.     0x000,        /* background color */
  45.     0x500
  46. };
  47.  
  48. extern int Enable_Abort;
  49.  
  50. RP *rp;
  51. VP *vp;
  52. static SCR *Scr;
  53. static WIN *Win;
  54. static TA   Ta = {  (ubyte *)"topaz.font", 11 };
  55. static NS   Ns = {  0, 0, 0, 0, 1, -1, -1, HIRES|LACE, CUSTOMSCREEN|SCREENQUIET
  56.  &Ta };
  57. static NW   Nw = { 0, 0, 0, 0, 2, 1, NULL, BORDERLESS|NOCAREREFRESH|BACKDROP,
  58. NULL, NULL,NULL,NULL,NULL,0,0,8000,8000,CUSTOMSCREEN};
  59.  
  60. static long offset, scale1, scale2, flags;
  61. static long count, trails, nice, all;
  62. static long input, maxlines, ctemp;
  63. static long point1[MAXLINES+1][2], point2[MAXLINES+1][2], direction[2][2];
  64.  
  65. static char *TStr = "BOING!";
  66. static long TLen = 6;
  67.  
  68. void
  69. InitScrStructures()
  70. {
  71.     SCR scr;
  72.     if (GetScreenData(&scr, sizeof(scr), WBENCHSCREEN, NULL)) {
  73.     if (scr.ViewPort.Modes & HIRES)
  74.         MAXX = scr.Width;
  75.     else
  76.         MAXX = scr.Width * 2;
  77.     if (scr.ViewPort.Modes & LACE)
  78.         MAXY = scr.Height;
  79.     else
  80.         MAXY = scr.Height * 2;
  81.     } else {
  82.     MAXX = 640;
  83.     MAXY = 200;
  84.     }
  85.     Ns.Width  = MAXX;
  86.     Nw.Width  = MAXX;
  87.     Ns.Height = MAXY;
  88.     Nw.Height = MAXY;
  89. }
  90.  
  91. main(argc,argv)
  92. int argc;
  93. char *argv[];
  94. {
  95.     int var;
  96.     IORequest AddReq;    /* for dmouse ipc    */
  97.     IORequest RemReq;
  98.     PORT    *dmport;
  99.     PORT    *ipport;
  100.     char    foo;    /*  dummy variable, address used as id    */
  101.     short   notdone = 1;
  102.  
  103.     input  = 3;     /* Some defaults for switches */
  104.     trails = 1;
  105.     maxlines = 20;
  106.     nice  = FALSE;
  107.     all   = FALSE;
  108.     flags = LINES;
  109.  
  110.  
  111.     Enable_Abort = 0;
  112.  
  113.     while(--argc >= 1) {
  114.     switch (argv[argc][0]) {
  115.         case '-':
  116.         switch (argv[argc][1]) {
  117.             case 'T':
  118.             flags = TEXTSTR;
  119.             TStr = &argv[argc][2];
  120.             if (TStr[0] != \0)
  121.                 TLen = strlen(TStr);
  122.             break;
  123.             case 's':
  124.             flags = SPLINES;
  125.             break;
  126.             case 't':
  127.             trails = 0;
  128.             break;
  129.             case 'n':
  130.             nice = TRUE;
  131.             break;
  132.             case 'l':
  133.             maxlines = atoi(&argv[argc][2]);
  134.             maxlines = (maxlines > MAXLINES) ? MAXLINES : (maxlines < 1) ? 1 : maxlines;
  135.             break;
  136.             case 'c':
  137.             ctemp = atoi(&argv[argc][2]);
  138.             coltbl[1] = (ctemp > 4096) ? 4096 : (ctemp < 1) ? 1 : ctemp;
  139.             break;
  140.             case 'b':
  141.             flags = BOXES;
  142.             break;
  143.             case 'e':
  144.             flags = ELLIPSES;
  145.             break;
  146.             case 'a':
  147.             all = TRUE;
  148.             break;
  149.             default:
  150.             exit(20);
  151.         }
  152.         break;
  153.         default:
  154.         input = atoi(argv[argc]);
  155.         break;
  156.     }
  157.     }
  158.  
  159.     input = (input > 9) ? 9 : (input < 0) ? 1 : input;
  160.  
  161.     count = 0;
  162.     scale1 = 2;
  163.     scale2 = 2;
  164.     offset = 0;
  165.  
  166.     ipport = CreatePort(NULL, 0);   /*  ipc port    */
  167.  
  168.     if (openlibs(INTUITION_LIB|GRAPHICS_LIB) == 0)
  169.     goto fail;
  170.  
  171.     InitScrStructures();
  172.  
  173.     for(var = 0; var < VBeamPos(); ++var)
  174.     get_rand_point();
  175.  
  176.     point1[0][0] = get_rand_point();    /* Initial start x,y (one endpoint) */
  177.     point1[0][1] = get_rand_point();
  178.  
  179.     point2[0][0] = get_rand_point();
  180.     point2[0][1] = get_rand_point();
  181.  
  182.     for(var = 0; var < 2; ++var){
  183.     direction[var][0] = get_rand_dir();
  184.     direction[var][1] = get_rand_dir();
  185.     }
  186.  
  187.     AddReq.io_Message.mn_ReplyPort = ipport;
  188.     AddReq.io_Command = 0x84;
  189.     AddReq.io_Unit = (struct Unit *)&foo;
  190.     AddReq.io_Flags = 0x0C;    /* %1100 (screen blanker, no mouse blanker) */
  191.  
  192.     RemReq.io_Message.mn_ReplyPort = ipport;
  193.     RemReq.io_Command = 0x85;
  194.     RemReq.io_Unit = (struct Unit *)&foo;
  195.  
  196.     Forbid();
  197.     if (dmport = FindPort("DMouse.ipc"))
  198.     PutMsg(dmport, &AddReq.io_Message);
  199.     Permit();
  200.     if (dmport == NULL) {
  201.     puts("DMouse not running or <V1.20");
  202.     goto fail;
  203.     }
  204.  
  205.     while (notdone) {
  206.     long mask = SIGBREAKF_CTRL_C | (1 << ipport->mp_SigBit);
  207.     if (Scr)
  208.         mask = SetSignal(0L, mask);
  209.     else
  210.         mask = Wait(mask);
  211.  
  212.     if (mask & SIGBREAKF_CTRL_C)
  213.         notdone = 0;
  214.     if (mask & (1 << ipport->mp_SigBit)) {
  215.         IORequest *ior;
  216.         while (ior = (IORequest *)GetMsg(ipport)) {
  217.         if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  218.             notdone = 0;
  219.             continue;
  220.         }
  221.         switch(ior->io_Command) {
  222.         case 0x82:
  223.             screenon();
  224.             break;
  225.         case 0x83:
  226.             screenoff();
  227.             break;
  228.         case 0x86:
  229.             notdone = 0;
  230.             break;
  231.         }
  232.         ReplyMsg(&ior->io_Message);
  233.         }
  234.     }
  235.     if (Win)
  236.         LineArt();
  237.     }
  238.     screenon();
  239.     PutMsg(dmport, &RemReq.io_Message);
  240.     {
  241.     register IORequest *ior = NULL;
  242.     while (ior != &AddReq) {
  243.         WaitPort(ipport);
  244.         ior = (IORequest *)GetMsg(ipport);
  245.         if (ior->io_Message.mn_Node.ln_Type == NT_MESSAGE)
  246.         ReplyMsg(&ior->io_Message);
  247.     }
  248.     }
  249. fail:
  250.     DeletePort(ipport);
  251.     closelibs(-1);
  252. }
  253.  
  254. screenoff()
  255. {
  256.     if (Scr)
  257.     ScreenToFront(Scr);
  258.     else if (Scr = OpenScreen(&Ns)) {
  259.     Nw.Screen = Scr;
  260.     if (Win = OpenWindow(&Nw)){
  261.         vp = &Scr->ViewPort;
  262.         rp = Win->RPort;
  263.         LoadRGB4(vp,coltbl,2L);
  264.     }
  265.     ShowTitle(Scr, FALSE);
  266.     }
  267. }
  268.  
  269. screenon()
  270. {
  271.     if (Win)
  272.     CloseWindow(Win);
  273.     if (Scr)
  274.     CloseScreen(Scr);
  275.     Win = NULL;
  276.     Scr = NULL;
  277.     vp = NULL;
  278.     rp = NULL;
  279. }
  280.  
  281. LineArt()
  282. {
  283.     register int newoffset, tempx, tempy;
  284.  
  285.     SetAPen(rp, 1L);
  286.  
  287.     if (nice)
  288.     WaitTOF();
  289.  
  290.     switch (flags) {
  291.     case LINES:
  292.     Move(rp, point1[offset][0], point1[offset][1]);
  293.     Draw(rp, point2[offset][0], point2[offset][1]);
  294.     break;
  295.     case ELLIPSES:
  296.     doellipse(offset);
  297.     break;
  298.     case BOXES:
  299.     dobox(offset);
  300.     break;
  301.     case SPLINES:
  302.     dospline(offset);
  303.     break;
  304.     case TEXTSTR:
  305.     doteresa(offset);
  306.     break;
  307.     }
  308.  
  309.     if (checkbounce1(offset)) {
  310.     tempx = direction[0][0];
  311.     tempy = direction[0][1];
  312.  
  313.     direction[0][0] = (point1[offset][0] <= MINBOUND) ? 1 :
  314.     (point1[offset][0] >= BOUNDX) ? -1 :
  315.     get_rand_dir();
  316.  
  317.     direction[0][1] = (point1[offset][1] <= MINBOUND) ? 1 :
  318.     (point1[offset][1] >= BOUNDY) ? -1 :
  319.     get_rand_dir();
  320.  
  321.     scale1 = get_rand_scale();
  322.     }
  323.  
  324.     if (checkbounce2(offset)) {
  325.     tempx = direction[1][0];
  326.     tempy = direction[1][1];
  327.  
  328.     direction[1][0] = (point2[offset][0] <= MINBOUND) ? 1 :
  329.     (point2[offset][0] >= BOUNDX) ? -1 :
  330.     get_rand_dir();
  331.  
  332.     direction[1][1] = (point2[offset][1] <= MINBOUND) ? 1 :
  333.     (point2[offset][1] >= BOUNDY) ? -1 :
  334.     get_rand_dir();
  335.  
  336.     scale2 = get_rand_scale();
  337.     }
  338.  
  339.     if ((++count > 60000) | (count > 2500 && (flags == ELLIPSES))) {
  340.     count = maxlines;
  341.     if (trails == 0 | all) {
  342.         count = 0;
  343.         offset = 0;
  344.         Move(rp, 0, 0);
  345.         ClearScreen(rp);
  346.     }
  347.     if (all) {
  348.         flags = flags << 1;
  349.         if (flags > TEXTSTR)
  350.         flags = ELLIPSES;
  351.     }
  352.     }
  353.  
  354.     if (++offset > maxlines){
  355.     coltbl[1]++;
  356.     LoadRGB4(vp,coltbl,2L);
  357.     if ((coltbl[1] && 0x00f) > 0xb) {
  358.         coltbl[1] = coltbl[1] & 0xff0;
  359.         coltbl[1] += 0x010;
  360.     }
  361.     if ((coltbl[1] && 0x0f0) > 0xb0) {
  362.         coltbl[1] = coltbl[1] & 0xf0f;
  363.         coltbl[1] += 0x100;
  364.     }
  365.     if ((coltbl[1] && 0xf00) > 0xb00) {
  366.         coltbl[1] = ctemp;
  367.     }
  368.     }
  369.  
  370.     if (offset > maxlines)
  371.     offset = 0;
  372.  
  373.     /* Erase the oldest line... (or ellipse) */
  374.  
  375.     if (count > maxlines-1) {
  376.     newoffset = (offset == maxlines) ? 0 : offset + trails;
  377.     SetAPen(rp, 0L);
  378.     switch (flags) {
  379.     case LINES:
  380.         Move(rp, point1[newoffset][0], point1[newoffset][1]);
  381.         Draw(rp, point2[newoffset][0], point2[newoffset][1]);
  382.         break;
  383.     case ELLIPSES:
  384.         doellipse(newoffset);
  385.         break;
  386.     case BOXES:
  387.         dobox(newoffset);
  388.         break;
  389.     case SPLINES:
  390.         dospline(newoffset);
  391.         break;
  392.     case TEXTSTR:
  393.         doteresa(newoffset);
  394.         break;
  395.     }
  396.     SetAPen(rp, 1L);
  397.     }
  398.  
  399.     /* Calculate the next point */
  400.  
  401.     newoffset = (offset > 0) ? offset-1 : maxlines;
  402.     point1[offset][0] = (scale1 * direction[0][0]) + point1[newoffset][0];
  403.     point1[offset][1] = (scale1 * direction[0][1]) + point1[newoffset][1];
  404.  
  405.     if (flags != TEXTSTR){
  406.       point2[offset][0] = (scale2 * direction[1][0]) + point2[newoffset][0];
  407.       point2[offset][1] = (scale2 * direction[1][1]) + point2[newoffset][1];
  408.     } else {
  409.       point2[offset][0] = point1[offset][0] + TextLength(rp, TStr, TLen);
  410.       point2[offset][1] = point1[offset][1];
  411.     }
  412. }
  413.  
  414. doteresa(offset)
  415. int offset;
  416. {
  417.     register short x,y;
  418.  
  419.     x = (Scr->Width - TextLength(rp, TStr, TLen) - 20);
  420.     y = (Scr->Height- Scr->RastPort.TxHeight - Scr->RastPort.TxBaseline - 8);
  421.  
  422.     if (x < 0 || y < 0)
  423.     return;
  424.  
  425.     x = (x < point1[offset][0]) ? x : point1[offset][0];
  426.     y = (y < point1[offset][1]) ? y : point1[offset][1];
  427.  
  428.     Move(rp, x, y);
  429.     Text(rp, TStr, TLen);
  430. }
  431.  
  432. doellipse(newoffset)
  433. register int newoffset;
  434. {
  435.     register int tempx,tempy;
  436.  
  437.     tempx = (point2[newoffset][0] > point1[newoffset][0]) ?
  438.     point2[newoffset][0] - point1[newoffset][0] :
  439.     point1[newoffset][0] - point2[newoffset][0];
  440.  
  441.     tempy = (point2[newoffset][1] > point1[newoffset][1]) ?
  442.     point2[newoffset][1] - point1[newoffset][1] :
  443.     point1[newoffset][1] - point2[newoffset][1];
  444.  
  445.     tempx = (tempx > point1[newoffset][0]) ? point1[newoffset][0] :
  446.     ((tempx + point1[newoffset][0]) > BOUNDX) ? BOUNDX - point1[newoffset][0] :
  447.     tempx;
  448.  
  449.     tempy = (tempy > point1[newoffset][1]) ? point1[newoffset][1] :
  450.     ((tempy + point1[newoffset][1]) > BOUNDY) ? BOUNDY - point1[newoffset][1] :
  451.     tempy;
  452.  
  453.     tempx = (tempx > MAXELLIPSE) ? MAXELLIPSE : tempx;
  454.     tempy = (tempy > MAXELLIPSE) ? MAXELLIPSE : tempy;
  455.  
  456.     if (tempx > 0 && tempy > 0)
  457.     DrawEllipse(rp, point1[newoffset][0], point1[newoffset][1], tempx, tempy);
  458. }
  459.  
  460. dobox(offset)
  461. register int offset;
  462. {
  463.     register int tempx, tempy;
  464.  
  465.     Move(rp, point1[offset][0], point1[offset][1]);
  466.     Draw(rp, point2[offset][0], point2[offset][1]);
  467.  
  468.     tempx = MAXX - point1[offset][0];
  469.     tempy = MAXY - point1[offset][1];
  470.  
  471.     if (tempx >= 0 && tempy >= 0)
  472.     Draw(rp, tempx, tempy);
  473.  
  474.     tempx = MAXX - point2[offset][0];
  475.     tempy = MAXY - point2[offset][1];
  476.  
  477.     if (tempx >= 0 || tempy >= 0)
  478.     Draw(rp, tempx, tempy);
  479.  
  480.     Draw(rp, point1[offset][0], point1[offset][1]);
  481. }
  482.  
  483. long checkbounce1(index)
  484. register int index;
  485. {
  486.  
  487.     return (point1[index][0] >= BOUNDX) | (point1[index][1] >= BOUNDY) |
  488.         (point1[index][0] <= MINBOUND) | (point1[index][1] <= MINBOUND);
  489. }
  490.  
  491. long checkbounce2(index)
  492. register int index;
  493. {
  494.     return (point2[index][0] >= BOUNDX) | (point2[index][1] >= BOUNDY) |
  495.         (point2[index][0] <= MINBOUND) | (point2[index][1] <= MINBOUND);
  496. }
  497.  
  498. int get_rand_point()
  499. {
  500.     register short temp;
  501.  
  502.     temp = ran();
  503.     if (temp < 0)
  504.     temp = temp * -1;
  505.     temp = temp/319+19;
  506.  
  507.     return (temp > MAXY) ? MAXY : temp ;
  508. }
  509.  
  510. int get_rand_dir()
  511. {
  512.     register short num;
  513.  
  514.     num = ran((short)3);
  515.  
  516.     return (num < -5000) ? -1 : (num > 5000) ? 1 : 0;
  517. }
  518.  
  519. int get_rand_scale()
  520. {
  521.     register short temp;
  522.  
  523.     temp = ran();
  524.     if (temp < 0)
  525.     temp = temp * -1;
  526.     temp = temp/6560 + (short)input;
  527.  
  528.     return (temp > 17) ? 17 : temp;
  529. }
  530.  
  531. #define MAXPOINTS 5
  532. #define FIX(x) (((long)(x)) << 7)
  533.  
  534. /*
  535.  *   Draws a spline!  Expects all arguments in registers.
  536.  */
  537. #asm
  538.     public    _Draw
  539.     cseg
  540. rspline
  541.     move.l    a0,d0
  542.     sub.l    d6,d0
  543.     move.l    d0,d3
  544.     bpl    save1
  545.     neg.l    d0
  546. save1
  547.     move.l    a1,d1
  548.     sub.l    d7,d1
  549.     move.l    d1,d4
  550.     bpl    save2
  551.     neg.l    d1
  552. save2
  553.     move.l    d0,d2
  554.     cmp.l    d0,d1
  555.     bmi    save3
  556.     lsr.l    #3,d2
  557.     bra    save9
  558. save3
  559.     lsr.l    #3,d1
  560. save9
  561.     add.l    d1,d2
  562.     asr.l    #3,d2
  563.     asr.l    #5,d3
  564.     asr.l    #5,d4
  565.     move.l    a2,d0
  566.     sub.l    a0,d0
  567.     move.l    a3,d1
  568.     sub.l    a1,d1
  569.     asr.l    #5,d0
  570.     asr.l    #5,d1
  571.     muls.w    d4,d0
  572.     muls.w    d3,d1
  573.     sub.l    d1,d0
  574.     bpl    save4
  575.     neg.l    d0
  576. save4
  577.     cmp.l    d0,d2
  578.     bmi    pushem
  579.     move.l    a5,d0
  580.     sub.l    a0,d0
  581.     move.l    a6,d1
  582.     sub.l    a1,d1
  583.     asr.l    #5,d0
  584.     asr.l    #5,d1
  585.     muls.w    d4,d0
  586.     muls.w    d3,d1
  587.     sub.l    d1,d0
  588.     bpl    save5
  589.     neg.l    d0
  590. save5
  591.     cmp.l    d0,d2
  592.     bmi    pushem
  593. makeline
  594.     lsr.l    #7,d7
  595.     move.l    d7,-(sp)
  596.     lsr.l    #7,d6
  597.     move.l    d6,-(sp)
  598.     move.l    _rp,-(sp)
  599.     jsr    _Draw
  600.     add.w    #12,a7
  601.     rts
  602. pushem
  603.     movem.l d6/d7,-(sp)
  604.     move.l    a5,d0
  605.     add.l    d6,d0
  606.     asr.l    #1,d0
  607.     move.l    a6,d1
  608.     add.l    d7,d1
  609.     asr.l    #1,d1
  610.     movem.l d0/d1,-(sp)
  611.     move.l    a2,d2
  612.     add.l    a5,d2
  613.     asr.l    #1,d2
  614.     move.l    a3,d3
  615.     add.l    a6,d3
  616.     asr.l    #1,d3
  617.     move.l    d0,d4
  618.     add.l    d2,d4
  619.     asr.l    #1,d4
  620.     move.l    d1,d5
  621.     add.l    d3,d5
  622.     asr.l    #1,d5
  623.     movem.l d4/d5,-(sp)
  624.     move.l    a0,d6
  625.     add.l    a2,d6
  626.     asr.l    #1,d6
  627.     move.l    a1,d7
  628.     add.l    a3,d7
  629.     asr.l    #1,d7
  630.     move.l    d2,d0
  631.     add.l    d6,d0
  632.     asr.l    #1,d0
  633.     move.l    d3,d1
  634.     add.l    d7,d1
  635.     asr.l    #1,d1
  636.     move.l    d6,a2
  637.     move.l    d7,a3
  638.     move.l    d0,d6
  639.     add.l    d4,d6
  640.     asr.l    #1,d6
  641.     move.l    d1,d7
  642.     add.l    d5,d7
  643.     asr.l    #1,d7
  644.     movem.l d6/d7,-(sp)
  645.     move.l    d0,a5
  646.     move.l    d1,a6
  647.     jsr    rspline
  648.     movem.l (sp)+,a0/a1
  649.     movem.l (sp)+,a2/a3/a5/a6
  650.     movem.l (sp)+,d6/d7
  651.     bra    rspline
  652. #endasm
  653. /*
  654.  *   Now our linkage to the spline routine.  Parameters are in 8(a5)...
  655.  */
  656. int drawspline(x1, y1, x2, y2, x3, y3, x4, y4)
  657. long x1, y1, x2, y2, x3, y3, x4, y4 ;
  658. {
  659. #asm
  660.     movem.l saver,-(sp)
  661.     move.l    8(a5),a0
  662.     move.l    12(a5),a1
  663.     move.l    16(a5),a2
  664.     move.l    20(a5),a3
  665.     move.l    28(a5),a6
  666.     move.l    32(a5),d6
  667.     move.l    36(a5),d7
  668.     move.l    24(a5),a5
  669.     jsr    rspline
  670.     movem.l (sp)+,saver
  671. saver    reg    d0-d7/a0-a6
  672. #endasm
  673. }
  674.  
  675. /*
  676.  *   Here we draw splines!  Magic, you know.
  677.  */
  678. dospline(index)
  679. register int index;
  680. {
  681.     int index1;
  682.  
  683.     if (index == 0)
  684.     index1 = maxlines;
  685.     else
  686.     index1 = index - 1;
  687.  
  688.     Move(rp, (long)(point1[index][0]), (long)(point1[index][1])) ;
  689.     drawspline(FIX(point1[index][0]), FIX(point1[index][1]),
  690.           FIX(point2[index][1]), FIX(point2[index][1]),
  691.           FIX(point1[index1][0]), FIX(point1[index1][1]),
  692.           FIX(point2[index1][0]), FIX(point2[index1][1])) ;
  693. }
  694.  
  695.  
  696.