/* ** Simple example of dynamic simplerefresh window ** ** Properly allocates screen pens under OS 3.0++, handles resize etc. ** ** Written by Harry "Piru" Sintonen ** Public Domain. ** */ #include #include #include #include #include #include #include #include #include WORD *allocpens(struct Screen *scr); void freepens(WORD *pens, struct Screen *scr); void render(struct Window *win, WORD *pens); void clearwindow(struct Window *win); enum { P_WHITE, P_BLUE, NUMPENS }; static const ULONG penrgb[NUMPENS] = { 0xFFFFFF, 0x0000FF, }; /* Fallback pens for OS 2.x and error conditions */ static const WORD staticpens[] = { 2, /* white */ 3, /* blue */ }; int main(void) { struct Window *win; win = OpenWindowTags(NULL, WA_Left, 20, WA_Top, 20, WA_Width, 320, WA_Height, 200, WA_MinWidth, 32, WA_MinHeight, 20, WA_MaxWidth, ~0, WA_MaxHeight, ~0, WA_AutoAdjust, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_REFRESHWINDOW | IDCMP_SIZEVERIFY | IDCMP_NEWSIZE, WA_Title, "example window", WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_SizeGadget, TRUE, WA_Activate, TRUE, WA_RMBTrap, TRUE, WA_SimpleRefresh, TRUE, TAG_DONE); if (win) { WORD *pens; struct MsgPort *port; ULONG wmask; int running; pens = allocpens(win->WScreen); render(win, pens); port = win->UserPort; wmask = 1UL << port->mp_SigBit; running = TRUE; do { ULONG sigs; sigs = Wait(wmask | SIGBREAKF_CTRL_C); if (sigs & wmask) { struct IntuiMessage *imsg; while ((imsg = (APTR) GetMsg(port))) { switch (imsg->Class) { case IDCMP_CLOSEWINDOW: running = FALSE; break; case IDCMP_RAWKEY: if (imsg->Code == (IECODE_UP_PREFIX | 0x45)) /* ESC */ { running = FALSE; } break; case IDCMP_REFRESHWINDOW: BeginRefresh(win); render(win, pens); EndRefresh(win, TRUE); break; case IDCMP_SIZEVERIFY: /* Do nothing; this flag is only requested to * syncronize the begining of resize. Useful if we're * busy rendering something and we don't want to render * over the borders on window shrink. Not really needed * here, but I wanted to use this space for education. */ break; case IDCMP_NEWSIZE: render(win, pens); break; } ReplyMsg(&imsg->ExecMessage); } } if (sigs & SIGBREAKF_CTRL_C) { running = FALSE; } } while (running); clearwindow(win); freepens(pens, win->WScreen); CloseWindow(win); } return 0; } static ULONG mk32gun(UBYTE val) { ULONG n; n = val & 0xf; n = (n << 4) | n; n = (val << 24) | (n << 16) | (n << 8) | (n << 0); return n; } WORD *allocpens(struct Screen *scr) { if (GfxBase->LibNode.lib_Version >= 39) { WORD *pens; pens = AllocMem(sizeof(WORD) * NUMPENS, MEMF_ANY); if (pens) { struct ColorMap *cm; int i; cm = scr->ViewPort.ColorMap; for (i = 0; i < NUMPENS; i++) { pens[i] = ObtainBestPen(cm, mk32gun((penrgb[i] & 0xff0000) >> 16), mk32gun((penrgb[i] & 0x00ff00) >> 8), mk32gun((penrgb[i] & 0x0000ff) >> 0), OBP_Precision, PRECISION_GUI, OBP_FailIfBad, FALSE, TAG_DONE); } return pens; } } /* Fallback to static pens if something fails */ return (WORD *) staticpens; } void freepens(WORD *pens, struct Screen *scr) { if (pens != (WORD *) staticpens) { struct ColorMap *cm; int i; cm = scr->ViewPort.ColorMap; /* This avoids some nasty artefacts if something should still be * rendering while the pens are being released. */ WaitBlit(); for (i = 0; i < NUMPENS; i++) { if (pens[i] != -1) { ReleasePen(cm, pens[i]); } } FreeMem(pens, sizeof(WORD) * NUMPENS); } } void render(struct Window *win, WORD *pens) { LONG l, t, w, h; l = win->BorderLeft; t = win->BorderTop; w = win->Width - l - win->BorderRight; h = win->Height - t - win->BorderBottom; if (w <= 0 || h <= 0) { /* Window inside is totally invisible, don't bother */ return; } /* White background */ SetAPen(win->RPort, pens[P_WHITE]); RectFill(win->RPort, l, t, l + w - 1, t + h - 1); /* Blue ellipse */ SetAPen(win->RPort, pens[P_BLUE]); DrawEllipse(win->RPort, l + (w - 1) / 2, t + (h - 1) / 2, (w - 1) / 2, (h - 1) / 2); } void clearwindow(struct Window *win) { LONG l, t, w, h; l = win->BorderLeft; t = win->BorderTop; w = win->Width - l - win->BorderRight; h = win->Height - t - win->BorderBottom; if (w <= 0 || h <= 0) { /* Window inside is totally invisible, don't bother */ return; } /* Clear window inside */ SetAPen(win->RPort, 0); RectFill(win->RPort, l, t, l + w - 1, t + h - 1); }