[comp.sys.amiga] Dmouse "feature"

mp1u+@andrew.cmu.edu (Michael Portuesi) (05/19/88)

Dmouse does not recognize the Intuition keyboard equivalents of the
mouse and mouse buttons, but instead passes them on to Intuition to
interpret.  So if you want to place a mouse click in a window but
*not* bring it to the front, place the pointer in the window and hit
Alt-LeftAmiga (or Alt-Commodore, depending on your keyboard).

If you turn off the automatic window activation feature, you can use
this "feature" to change the active window without disturbing the
depth arrangment of the windows.

<poof>

I suspect the reason Matt does not want to include a clock in Dmouse
is one of philosophy -- Dmouse is an INPUT handler, and clocks have
very little to do with input.  If you want a clock, why not run your
own?  I use the "title bar" clock myself;  if you use interlace, the
ledclock by Ali Ozer is really cool.

			    --M


Michael Portuesi / Carnegie Mellon University
ARPA/UUCP: mp1u+@andrew.cmu.edu		BITNET: rainwalker@drycas

"Memories are uncertain friends, when recalled by messages" -- OMD, "Messages"

rokicki@polya.STANFORD.EDU (Tomas G. Rokicki) (05/19/88)

> If you use interlace, the ledclock by Ali Ozer is really cool.

I've hacked it ever so slightly to make it work on non-interlace.
It's so short, that here it is!  (Manx only.)

/* LedClock (C)1987 Ali T. Ozer. A clock program for interlaced screens. */

#include <exec/types.h>
#include <functions.h>
#include <intuition/intuition.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <graphics/gfxmacros.h>

/* LedClock is freely distributable and NOT for sale. 
**
** Author: Ali T. Ozer, ARPA: ali@score.stanford.edu, 
**                      REAL: Box 7703, Stanford, CA 94309
**
** A clock program for interlaced screens. This one uses
** numbers that resemble the numbers used in 7-segment LED and LCD
** clock displays. Various options are provided as compile time "#define"s:
**  
** TWENTYFOURHOUR  0 or 1, determines if the clock is 24-hour or not
** WINDOWXLOC      starting X location for the window in the WB screen
** WINDOWYLOC      starting Y location for the window in the WB screen
** FANCYPANIC      0 or 1, determines if a error message box is shown in
**                 case the clock can't run...
**
** LedClock works best with interlaced screens --- It will look ugly on a 
** "normal" WorkBench screen. (It will probably look fine on a lo-res, non
** interlaced screen, except it will be too big, way too big.)
**
** LedClock can be compiled by Manx 3.40a. Use the "+c" and "+d" switches
** while linking to assure that the static images go into CHIP ram:
**
**   cc ledclock.c
**   ln +cd ledclock.o -lc
**   run ledclock
**
** During linking you'll get warnings about _cli_parse and _wb_parse being
** redefined; you can safely ignore these messages.
**
** Various corners have been cut from this program to make the executable small.
** With Manx 3.40a, the executable is somewhere around 3.1 Kbytes. One can
** probably achieve half that size in assembly.
**
** Programmers might wish to fool around with the code to customize the
** clock. It's amazing how many parameters one can think of if one tries
** to make a general program... So, rather than trying to provide zillions
** of command line arguments, I took the easy way out and just threw out
** all generality... If you wish to create your customized clocks from
** this code, feel free to do so --- but please keep my original copyright
** notice (in the screen title bar) intact, along with any additional
** copyright notices you might add.
*/

/* The next few define's can be changed for different runtime parameters... */

#define TWENTYFOURHOUR 1
#define FANCYPANIC     0
#define WINDOWXLOC     450
#define WINDOWYLOC     0

#define COPYRIGHT "LedClock 1.0 (C)1987 Ali T. Ozer"

#if FANCYPANIC
#define Panic(arg)  WarnUser(arg)
#else 
#define Panic(arg)  CloseThings(1)
#endif

#define DIGITMAXX 18
#define DIGITMAXY 16

#define WINDOWX 0
#define WINDOWY 9
#define DIGIT1X (WINDOWX + 3)
#define DIGIT2X (DIGIT1X + DIGITMAXX + 3)
#define DIGIT3X (DIGIT2X + DIGITMAXX + 10)
#define DIGIT4X (DIGIT3X + DIGITMAXX + 3)
#define DIGITY  (WINDOWY + 3)
#define WINDOWWIDTH  (DIGIT4X + DIGITMAXX + 3)
#define WINDOWHEIGHT (DIGITY + DIGITMAXY + 3)
#define COLONX  (DIGIT3X - 6)
#define COLONY  (DIGITY  + 5)

/* The "leds" (the segments making up the digits) are named in the standard
** (clockwise) fashion, with a = top led, b = right top, ... f = left top, and
** g = middle.
**
** The following describes the vertical leds ("b", "c", "e", and "f") 
*/
USHORT vled [] = {
 0xdfff, 0x8fff, 0x8fff, 0x8fff, 0x1fff, 0x1fff, 0x1fff };

/* The following is the bitmap description of leds a and d.
*/
USHORT hled [] = {0x807f, 0x807f};

/* The following is the bitmap description of the middle ("g") led.
*/
USHORT mled [] = {0x80ff, 0x80ff};

/* The following describes the bitmap for the colon and the image.
*/
USHORT colondata [] = {
0x8fff, 0x8fff, 0xffff, 0xffff, 0x1fff, 0x1fff };

struct Image colon = { 0,  0,  4, 6, 1, colondata, 1, 0, NULL};

/* The following describes the Image structures for all 7 leds, "a".."g"
*/
struct Image leds [] = {
{ 6,  0, 10,  2, 1, &hled[0], 1, 0, NULL},
{15,  1,  4,  7, 1, &vled[0], 1, 0, NULL},
{13,  8,  4,  7, 1, &vled[0], 1, 0, NULL},
{ 3, 15, 10,  2, 1, &hled[0], 1, 0, NULL},
{ 0,  8,  4,  7, 1, &vled[0], 1, 0, NULL},
{ 2,  1,  4,  7, 1, &vled[0], 1, 0, NULL},
{ 5,  7,  9,  2, 1, &mled[0], 1, 0, NULL}
};

/* In the following each byte determines what leds are lit for the 
** corresponding digit. The bits are ordered "xgfedcba" and a 1 means the 
** led is lit.
*/
UBYTE lled [] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

struct Window      *MyWin;
struct RastPort    *MyRP;
struct Library     *IntuitionBase;
struct Library     *GfxBase;
struct timerequest  MyTR;
unsigned long      WindowSig, TimerSig;
int                curminutes;

/* Draw digit puts a 7-segment digit at the specified location. If digit is
** negative, then the area is erased but nothing is drawn. 
*/
DrawDigit (rp, digit, xloc, yloc)
struct RastPort *rp;
int digit, xloc, yloc;
{
  register int ledmask, ledcnt = 0;
  
  /* First erase it */
  RectFill (rp, (long)xloc, (long)yloc, 
                (long)(xloc + DIGITMAXX), (long)(yloc + DIGITMAXY));

  if (digit >= 0) {
    ledmask = lled[digit];
    while (ledcnt != 7) {
      if (ledmask & 1) DrawImage (rp, &leds[ledcnt], (long)xloc, (long)yloc);
      ledcnt++; ledmask >>= 1;
    }
  }
}

/* OpenTimer will open the timer device and also do all the initialization
** necessary to send timer requests... 
*/
OpenTimer (tr)
struct timerequest *tr;
{
  struct MsgPort *timerport;

  while ((timerport = CreatePort (NULL, 0L)) == NULL) Panic ("No port");

  OpenDevice (TIMERNAME, UNIT_VBLANK, tr, 0L);
  tr->tr_node.io_Message.mn_ReplyPort = timerport;
  tr->tr_node.io_Command = TR_ADDREQUEST;

}

/* OpenThings opens the Amiga libraries, the window. and the timer.
** If something goes wrong, a requester will pop up to warn the user.
** (If FANCYPANIC is defined as zero, then no requester pops up --- the
** program just quits.)
*/
OpenThings ()
{
  static struct NewWindow MyWinInfo =
  { WINDOWXLOC, WINDOWYLOC, WINDOWWIDTH, WINDOWHEIGHT, /* Lft,Top,Wd,Hgt */
    -1,-1,                   /* Detail pen, Block pen (-1 = use screens) */
    CLOSEWINDOW,                                           /* IDCMPflags */
    SMART_REFRESH | WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | NOCAREREFRESH,
    NULL, NULL, NULL,              /* FirstGadget, Menu Checkmark, Title */
    NULL, NULL,                                        /* Screen, Bitmap */
    0, 0, 0, 0,                     /* Min Width/Height Max Width/Height */
    WBENCHSCREEN                                                 /* Type */
  };

  if (((IntuitionBase = OpenLibrary("intuition.library",0L)) == NULL) ||
      ((GfxBase = OpenLibrary("graphics.library",0L)) == NULL)) CloseThings (1);

  while (!(MyWin = OpenWindow(&MyWinInfo))) Panic ("No window");
  SetWindowTitles (MyWin, NULL, COPYRIGHT);

  MyRP = MyWin->RPort;
  WindowSig = 1L << MyWin->UserPort->mp_SigBit;

  SetOPen (MyRP, 1L); 
  SetAPen (MyRP, 1L);

  OpenTimer(&MyTR);
  TimerSig = 1L << MyTR.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
}  

/* SendTimerRequest sends a timer request for the indicated amount of seconds.
** Assumes the timer request block pointed to by tr has already been properly
** setup --- including the io_Command field. 
*/
SendTimerRequest (tr, seconds)
struct timerequest *tr;
unsigned long seconds;
{
  tr->tr_time.tv_micro = 0L;
  tr->tr_time.tv_secs  = seconds;
  SendIO (tr);
}
  
#if FANCYPANIC

/* WarnUser is called when something goes wrong during initialization.
** WarnUser assumes Intuition is opened! (Now if that's not the case,
** then you're in trouble...)
*/

WarnUser (reason)
UBYTE *reason;
{
  static struct IntuiText postxt  = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Retry",NULL};
  static struct IntuiText negtxt  = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Sigh",NULL};
  static struct IntuiText bodytxt = {3,1,COMPLEMENT,4,6,NULL,NULL,NULL};

  bodytxt.IText = reason;
  if (AutoRequest (NULL,&bodytxt,&postxt,&negtxt,0L,0L,300L,60L) == FALSE)
     CloseThings (1);
}

#endif

/* CloseTimer closes the timer pointed to by tr. If no reply port is present,
** then CloseTimer assumes the timer was never opened.
*/
CloseTimer (tr)
struct timerequest *tr;
{
  struct MsgPort *msgp;
  if (msgp = tr->tr_node.io_Message.mn_ReplyPort) {
    DeletePort (msgp);  
    CloseDevice (tr);
  }
}

/* CloseThings releases all the resources obtained by the program.
*/
CloseThings(error_code)
int error_code;
{ 
  CloseTimer(&MyTR);
  if (MyWin)         CloseWindow(MyWin);
  if (GfxBase)       CloseLibrary(GfxBase);
  if (IntuitionBase) CloseLibrary(IntuitionBase);
  exit (error_code);
}

static int ht = -1, ho = -1, mt = -1, mo = -1;

/* WriteTime writes out the new time. 
*/
WriteTime (minutes)
int minutes;
{
  int hours, htens, hones, mtens, mones;
  
#if TWENTYFOURHOUR
  hours = minutes / 60;
#else
  hours = (minutes / 60 + 11) % 12 + 1;
#endif
    
  /* AM if minutes < 720, but we don't worry about this... */

  if ((htens = hours / 10) != ht)
    DrawDigit (MyRP, ((ht = htens) ? ht : -1), DIGIT1X, DIGITY);
  if ((hones = hours % 10) != ho)
    DrawDigit (MyRP, ho = hones, DIGIT2X, DIGITY);
  if ((mtens = (minutes % 60) / 10) != mt)
    DrawDigit (MyRP, mt = mtens, DIGIT3X, DIGITY);
  if ((mones = (minutes % 10)) != mo)
    DrawDigit (MyRP, mo = mones, DIGIT4X, DIGITY);
}    

/* ShowTheTime reads the time, updates the display, and sends a new timer
** request.
*/
ShowTheTime ()
{
  long timevec[3];

  DateStamp (&timevec[0]);
  curminutes = (int)(timevec[1]);
  WriteTime (curminutes);
  /* Timer request for the next top of minute */
  SendTimerRequest (&MyTR, 60L - (long)(timevec[2] / 50L));
}

main ()
{
  struct Task *me;

  OpenThings  ();

  /* Bump the priority up to 5. Not too serious, as under normal conditions
  ** this program will wake up only every 60 seconds.
  */
  if (me = FindTask (NULL)) SetTaskPri (me, 5L); 

  /* Clear the window and draw in the ":". 
  */  
  RectFill  (MyRP, (long)WINDOWX, (long)WINDOWY, 
                    WINDOWWIDTH-1L, WINDOWHEIGHT-1L); 
  DrawImage (MyRP, &colon, (long)COLONX, (long)COLONY);

  /* Now sit down, relax, and wait for either an IDCMP or a timer event...
  */
  while (1) {
    ShowTheTime ();
    if (Wait (WindowSig | TimerSig) & TimerSig)
       (void) GetMsg (MyTR.tr_node.io_Message.mn_ReplyPort);
    else {  
       AbortIO (&MyTR);  /* Don't even get the message, assume it's CLOSEWINDOW */
       CloseThings (0);
    }
  }
}



/* Including the following two lines prevents the linker from bringing in
** the two functions _wb_parse and _cli_parse called by the initialization
** code in _main. Reduces code size by about 900 bytes for Manx 3.40a.
*/
void _wb_parse () {}
void _cli_parse () {}
-- 
    /-- Tomas Rokicki         ///  Box 2081  Stanford, CA  94309
   / o  Radical Eye Software ///                  (415) 326-5312
\ /  |  . . . or I       \\\///   Gig 'em, Aggies! (TAMU EE '85)
 V   |  won't get dressed \XX/ Bay area Amiga Developer's GroupE