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