home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / programming / c / oui / window.cc < prev    next >
C/C++ Source or Header  |  1998-04-23  |  14KB  |  571 lines

  1. // $Id: window.cc 1.5 1998/01/13 19:55:59 dlorre Exp $
  2. #include <exec/types.h>
  3. #include <graphics/gfxbase.h>
  4. #include <graphics/gfxmacros.h>
  5. #include <intuition/gadgetclass.h>
  6. #include <libraries/gadtools.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <mydebug.h>
  10.  
  11. #include "screen.h"
  12. #include "window.h"
  13. #include "locale.h"
  14. #include "gadgetlist.h"
  15. #include "gadgets/gadget.h"
  16. #include "gadgets/string.h"
  17. #include "gadgets/fbutton.h"
  18.  
  19. #include <proto/exec.h>
  20. #include <proto/graphics.h>
  21. #include <proto/layers.h>
  22. #include <proto/intuition.h>
  23. #include <proto/gadtools.h>
  24. #include <proto/utility.h>
  25. #include "compiler.h"
  26.  
  27. catalog  *ocat ;
  28. slist    *winlist ;
  29.  
  30. extern "C" {
  31. extern struct LocaleBase *LocaleBase ;
  32.  
  33. void _STI_4500_initouicat()
  34. {
  35.     ocat = new catalog("oui.catalog", "english", NULL) ;
  36. }
  37.  
  38. void _STD_4500_closeouicat()
  39. {
  40.     delete ocat ;
  41. }
  42.  
  43. void _STI_4500_initwinlist()
  44. {
  45.     winlist = new slist ;
  46. }
  47.  
  48. void _STD_4500_closewinlist()
  49. {
  50.     delete winlist ;
  51. }
  52. }
  53.  
  54. lstring  FAR ok NPARMS(ocat, "_Ok", "MSG_OK_GAD", 1) ;
  55. lstring  FAR cancel LPARMS(ocat, "_Cancel", "MSG_CANCEL_GAD") ;
  56. lstring  FAR parent LPARMS(ocat, "_Parent", "MSG_PARENT_GAD") ;
  57. lstring  FAR drawer LPARMS(ocat, "_Drawer:", "MSG_DRAWER_GAD") ;
  58. lstring  FAR file LPARMS(ocat, "_File:", "MSG_FILE_GAD") ;
  59. lstring  FAR comment LPARMS(ocat, "Co_mment:", "MSG_COMMENT_GAD") ;
  60.  
  61.  
  62. // Constructor
  63. // Initialisation of variables in a predefined state.
  64. window::window(short l, short t, short w, short h) : rectangle(l, t, w, h),
  65.                         ws(NULL),
  66.                         win(NULL),
  67.                         mp(NULL),
  68.                         idcmp(NULL),
  69.                         hasgadgets(FALSE),
  70.                         hasmenus(FALSE),
  71.                         active(FALSE),
  72.                         initok(FALSE),
  73.                         okflag(FALSE),
  74.                         g(NULL),
  75.                         rp(NULL),
  76.                         signal(NULL),
  77.                         reqfunc(NULL),
  78.                         tags(NULL),
  79.                         bgrp(NULL),
  80.                         bgbm(NULL),
  81.                         emode(0)
  82. {
  83.     link.win = this ;
  84.     winlist->addtail(&link) ;
  85. }
  86.  
  87.  
  88. window::~window()
  89. {
  90.     if (initok) close() ;
  91.     winlist->remove(&link) ;
  92. }
  93.  
  94.  
  95. // _open -- parameter list version
  96. // calls same function with arrays
  97. void window::_open(MsgPort *wp, ULONG iflags, ULONG data, ...)
  98. {
  99.     _open(wp, iflags, (TagItem *)&data) ;
  100. }
  101.  
  102. // _open -- var-array version
  103. // Calls OpenWindow, copy tags if any
  104. void __saveds window::_open(MsgPort *wp, ULONG iflags, TagItem *t)
  105. {
  106.     tags = CloneTagItems(t) ; // A NULL result in cloning tags is tolerated
  107.                               // Because either the window should fail or
  108.                               // the parameter passed is already NULL.
  109.                               // In other terms, the window will open
  110.                               // with default parameters if enough memory.
  111.     mp = wp ;
  112.  
  113.     // IDCMP_REFRESH...  obligatoire : il ne sera délivré aucun passe-droit.
  114.     idcmp = iflags | IDCMP_REFRESHWINDOW ;
  115.  
  116.     initok = active = FALSE ;
  117.     selfmsg = BOOL(!mp) ;
  118.     win = OpenWindowTags(NULL,
  119.         WA_Left,        left,
  120.         WA_Top,         top,
  121.         WA_InnerWidth,  width,
  122.         WA_InnerHeight, height,
  123.         WA_AutoAdjust,  TRUE,
  124.         WA_CustomScreen, (LONG)ws->scr,
  125.         TAG_MORE,       tags) ; // TAG_MORE is a terminaison point
  126.                                 // i.e. no TAG_DONE necessary.
  127.  
  128.     if (win) {
  129.         active = initok = TRUE ;
  130.         win->UserData = (BYTE *)this ;  // User data contains object pointer
  131.         rp = win->RPort ;
  132.         if (!selfmsg) win->UserPort = mp ;  // Shared message port
  133.         if (ModifyIDCMP(win, idcmp)) {      // idcmp is never NULL (refresh at least)
  134.             mp = win->UserPort ;
  135.             signal = 1 << mp->mp_SigBit ;
  136.         }
  137.         else {  // This is probably a signal allocation failure, try to free some
  138.             CloseWindow(win) ;
  139.             win = NULL ;
  140.             active = initok = FALSE ;
  141.         }
  142.     }
  143. }
  144.  
  145. void window::open(screen *nws)
  146. {
  147.     ws = nws ;
  148.     _open(NULL, IDCMP_CLOSEWINDOW,
  149.         WA_CloseGadget, TRUE,
  150.         TAG_DONE) ;
  151. }
  152.  
  153. void window::close()
  154. {
  155. Menu    *m ;
  156.  
  157.                     // initok indique que TOUTES les opérations à
  158.     if (initok) {   // l'initialisation ont réussi
  159.         if (tags) FreeTagItems(tags) ;
  160.         if (win) {
  161.             strip();
  162.             if (hasmenus) {
  163.                 ClearMenuStrip(win) ;
  164.                 while (menu) {
  165.                     m = menu->NextMenu ;
  166.                     FreeMenus(menu) ;
  167.                     menu = m ;
  168.                 }
  169.                 hasmenus = FALSE ;
  170.             }
  171.             CloseWindow(win) ;
  172.             if (hasgadgets) {
  173.                 delete g ;
  174.                 g = NULL ;
  175.                 hasgadgets = FALSE ;
  176.             }
  177.             win = NULL ;
  178.         }
  179.     }
  180.     initok = active = FALSE ;
  181. }
  182.  
  183.  
  184. void window::strip()
  185. {
  186.     Forbid();
  187.     stripimsg() ;
  188.     if (!selfmsg)
  189.         win->UserPort = NULL;
  190.     ModifyIDCMP(win, NULL);
  191.     Permit();
  192. }
  193.  
  194.  
  195. void window::stripimsg()
  196. {
  197. IntuiMessage *msg;
  198. Node *succ;
  199.  
  200.     msg = (IntuiMessage *) mp->mp_MsgList.lh_Head;
  201.  
  202.     while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {
  203.  
  204.         if( msg->IDCMPWindow ==  win ) {
  205.  
  206.             /* Intuition is about to free this message.
  207.              * Make sure that we have politely sent it back.
  208.              */
  209.             Remove( (Node *)msg );
  210.  
  211.             ReplyMsg( (Message *)msg );
  212.         }
  213.  
  214.         msg = (IntuiMessage *) succ;
  215.     }
  216. }
  217.  
  218.  
  219. void window::eventloop()
  220. {
  221. IntuiMessage *msg ;
  222.  
  223.     if (initok) {
  224.         while (active) {
  225.             Wait(signal) ;
  226.             while (msg = (IntuiMessage *)GetMsg(win->UserPort)) {
  227.                 processevents(msg) ;
  228.                 ReplyMsg((Message *)msg) ;
  229.             }
  230.         }
  231.     }
  232. }
  233.  
  234. void window::processevents(IntuiMessage *msg)
  235. {
  236. IntuiMessage    *gt_msg, smsg ;
  237. BOOL            doevents ;
  238. static Gadget   *curgad = NULL ;
  239. static ULONG    curattr ;
  240.  
  241.     gt_msg = NULL ;
  242.     doevents = FALSE ;
  243.     if (msg->Class & (IDCMP_MOUSEMOVE|IDCMP_GADGETUP|IDCMP_GADGETDOWN)) {
  244.         switch(msg->Class) {
  245.         case IDCMP_GADGETDOWN:
  246.             curgad = (Gadget *)msg->IAddress ;
  247.             curattr = ULONG(curgad->UserData) ;
  248.             if (!curattr) gt_msg = GT_FilterIMsg(msg) ;
  249.             break ;
  250.         case IDCMP_GADGETUP:
  251.             curgad = NULL ;
  252.             gt_msg = GT_FilterIMsg(msg) ;
  253.             break ;
  254.         case IDCMP_MOUSEMOVE:
  255.             if (curgad && curattr) {
  256.             ULONG code, res ;
  257.                 msg->IAddress = curgad ;
  258.                 res = GetAttr(curattr, curgad, &code) ;
  259.                 msg->Code = USHORT(res) ;
  260.                 doevents = TRUE ;
  261.             }
  262.             else {
  263.                 gt_msg = GT_FilterIMsg(msg) ;
  264.             }
  265.             break ;
  266.         }
  267.     }
  268.     else {
  269.         gt_msg = GT_FilterIMsg(msg) ;
  270.     }
  271.  
  272.  
  273.     if (doevents || gt_msg) {
  274.         doevents = TRUE ;
  275.         smsg = (gt_msg)?*gt_msg:*msg ;
  276.     }
  277.     GT_PostFilterIMsg(gt_msg) ;
  278.     if (doevents) simpleevent(&smsg) ;
  279. }
  280.  
  281. void window::simpleevent(IntuiMessage *msg)
  282. {
  283. MenuItem *item ;
  284. void (*menufunc)() ;
  285. TagItem *tags ;
  286. unsigned long id, classe ;
  287. USHORT code ;
  288. Gadget *gad ;
  289. gadget *gd ;
  290.  
  291.     code = msg->Code ;
  292.     classe = msg->Class ;
  293.     gad = (Gadget *)msg->IAddress ;
  294.     switch (classe) {
  295.         case IDCMP_CLOSEWINDOW:
  296.             active = FALSE ;
  297.             break ;
  298.         case IDCMP_MENUPICK:
  299.             if (hasmenus) {
  300.                 while (code != MENUNULL) {
  301.                     item = ItemAddress(menu, code);
  302.                     menufunc = (void (*)())GTMENUITEM_USERDATA(item);
  303.                     if (menufunc) {
  304.                         menufunc();
  305.                     }
  306.                     code = item->NextSelect;
  307.                 }
  308.             }
  309.             break ;
  310.         case IDCMP_IDCMPUPDATE:
  311.             tags = (TagItem *)gad ;
  312.             id = GetTagData(GA_ID, 0, tags) ;
  313.             gd = g->getgadget(id) ;
  314.             code = (unsigned short)GetTagData(ULONG(gd->gad->UserData), 0, tags) ;
  315.             g->processgadget(id, classe, code) ;
  316.             break ;
  317.         case IDCMP_GADGETUP:
  318.         case IDCMP_GADGETDOWN:
  319.         case IDCMP_MOUSEMOVE:
  320.             if (hasgadgets) {
  321.                 g->processgadget(gad->GadgetID, classe, code) ;
  322.             }
  323.             else if (gad->GadgetType & GTYP_REQGADGET)
  324.                 if (reqfunc) reqfunc(gad->GadgetID, classe, code) ;
  325.             break ;
  326.         case IDCMP_REFRESHWINDOW:
  327.             GT_BeginRefresh(win) ;
  328.             GT_EndRefresh(win, TRUE) ;
  329.             break ;
  330.         case IDCMP_VANILLAKEY:
  331.             handlevkey(code) ;
  332.             break ;
  333.         case IDCMP_RAWKEY:
  334.             handlerawkey(code) ;
  335.             break ;
  336.         case IDCMP_MOUSEBUTTONS:
  337.             handlemousebuttons(code, msg->MouseX, msg->MouseY, msg->Qualifier) ;
  338.             break ;
  339.     }
  340. }
  341.  
  342.  
  343. void window::setmenus(NewMenu *menu1, ...)
  344. {
  345. NewMenu **pmenu ;
  346. NewMenu *cmenu ;
  347. Menu *m, *pm ;
  348.  
  349.     menu = pm = NULL ;
  350.     pmenu = &menu1 ;
  351.     cmenu = *pmenu++ ;
  352.     while (cmenu) {
  353.         m = CreateMenus(cmenu,
  354.             TAG_DONE) ;
  355.         if (pm) {
  356.             pm->NextMenu = m ;
  357.             pm = m ;
  358.         }
  359.         else {
  360.             menu = pm = m ;
  361.         }
  362.         cmenu = *pmenu++ ;
  363.     }
  364.     LayoutMenus(menu, ws->vi,
  365.         GTMN_NewLookMenus,  TRUE,
  366.         TAG_DONE) ;
  367.  
  368.     SetMenuStrip(win, menu) ;
  369.     hasmenus = TRUE ;
  370. }
  371.  
  372.  
  373. void window::expandmenu(Menu *curm, NewMenu *extmenu)
  374. {
  375. Menu *sm, *pm, *nm ;
  376.  
  377.     if (!menu)                  // no menus ?
  378.         return ;
  379.  
  380.     sm = curm->NextMenu ;
  381.     if (curm == menu)
  382.         pm = NULL ;
  383.     else {
  384.         pm = menu ;
  385.         while (pm->NextMenu && pm->NextMenu != curm)
  386.             pm = pm->NextMenu ;
  387.     }
  388.  
  389.     nm = CreateMenus(extmenu,
  390.                 TAG_DONE) ;
  391.  
  392.     if (nm) {
  393.         ClearMenuStrip(win) ;
  394.         nm->NextMenu = sm ;
  395.         if (pm) pm->NextMenu = nm ;
  396.         LayoutMenus(menu, ws->vi,
  397.             GTMN_NewLookMenus, TRUE,
  398.             TAG_DONE) ;
  399.         SetMenuStrip(win, menu) ;
  400.         curm->NextMenu = NULL ;
  401.         FreeMenus(curm) ;
  402.     }
  403. }
  404.  
  405. void window::menuchanges(menustate *ms, LONG count)
  406. {
  407. long i ;
  408.  
  409.     ClearMenuStrip(win) ;
  410.     for (i=0; i<count; i++) {
  411.  
  412.         if (ms[i].checked)
  413.             ms[i].item->Flags |=  CHECKED ;
  414.         else
  415.             ms[i].item->Flags &= ~CHECKED ;
  416.  
  417.         if (ms[i].enable)
  418.             ms[i].item->Flags |=  ITEMENABLED ;
  419.         else
  420.             ms[i].item->Flags &=  ~ITEMENABLED ;
  421.  
  422.     }
  423.     ResetMenuStrip(win, menu) ;
  424. }
  425.  
  426.  
  427. short window::initarea(short w, short h, int size)
  428. {
  429. short retval = TRUE ;
  430.  
  431.     if (areaBuffer = new WORD[size]) {
  432.         if (areaInfo = new AreaInfo) {
  433.             if (tmpRas = new TmpRas) {
  434.                 if (GfxBase->LibNode.lib_Version >= 39) {
  435.                     tmpBitMap = AllocBitMap(w, h, 1,
  436.                         BMF_CLEAR|BMF_INTERLEAVED|BMF_DISPLAYABLE, ws->scr->RastPort.BitMap) ;
  437.                     if (!tmpBitMap)
  438.                         retval = FALSE ;
  439.                     else {
  440.                         tmpBuffer = tmpBitMap->Planes[0] ;
  441.                         InitTmpRas(tmpRas, tmpBuffer, tmpBitMap->BytesPerRow * h);
  442.                     }
  443.                 }
  444.                 else {
  445.                     tmpBuffer = (PLANEPTR)AllocRaster(w, h);
  446.                     if (!tmpBuffer)
  447.                         retval = FALSE ;
  448.                     else
  449.                         InitTmpRas(tmpRas, tmpBuffer, RASSIZE(w, h));
  450.                 }
  451.  
  452.                 if (retval) {
  453.                     InitArea(areaInfo, areaBuffer, (size*2)/5);
  454.                     awidth = w ;
  455.                     aheight = h ;
  456.                     asize = size ;
  457.                     rp->AreaInfo = areaInfo;
  458.                     rp->TmpRas = tmpRas;
  459.                 }
  460.             }
  461.         }
  462.     }
  463.     if (!retval) freearea() ;
  464.     return retval ;
  465. }
  466.  
  467. void window::freearea()
  468. {
  469.  
  470.     if (GfxBase->LibNode.lib_Version >= 39) {
  471.         if (tmpBitMap) FreeBitMap(tmpBitMap) ;
  472.     }
  473.     else
  474.         if (tmpBuffer) FreeRaster(tmpBuffer, awidth, aheight);
  475.     tmpBitMap = NULL ;
  476.     tmpBuffer = NULL ;
  477.  
  478.     if (tmpRas) {
  479.         delete tmpRas ;
  480.         tmpRas = NULL ;
  481.     }
  482.     if (areaInfo) {
  483.         delete areaInfo ;
  484.         areaInfo = NULL ;
  485.     }
  486.     if (areaBuffer) {
  487.         delete [] areaBuffer ;
  488.         areaBuffer = NULL ;
  489.     }
  490.  
  491. }
  492.  
  493.  
  494. void window::prepbox(BOOL center)
  495. {
  496. long mw = g->lmax(ok, cancel, NULL) + 20 ;
  497.  
  498.     g->box( ws->scr->WBorLeft+20,
  499.             g->maxh+8,
  500.             mw,
  501.             g->fontheight*3/2) ;
  502.  
  503.     g->setgpen(ws->xpens[GREEN_PEN]) ;
  504.     new fbutton(g, WFUNC(&window::fok), ok, TRUE) ;
  505.  
  506.     g->move(g->maxw-g->left-mw) ;
  507.     g->setgpen(ws->xpens[RED_PEN]) ;
  508.     new fbutton(g, WFUNC(&window::fcancel), cancel, FALSE) ;
  509.  
  510.  
  511.     width = short(g->maxw-ws->scr->WBorLeft+20) ;
  512.     height = short(g->maxh-ws->winbarheight+8) ;
  513.  
  514.     if (center) {
  515.         left = short((ws->width - width - ws->scr->WBorLeft-ws->scr->WBorRight) / 2) ;
  516.         top = short((ws->height - height - ws->winbarheight - ws->scr->WBorBottom) / 2) ;
  517.     }
  518.  
  519. }
  520.  
  521. void window::move(short dx, short dy)
  522. {
  523.     rectangle::move(dx, dy) ;
  524.     if (win) ChangeWindowBox(win, left, top, width, height) ;
  525. }
  526.  
  527. void window::size(short dw, short dh)
  528. {
  529.     rectangle::size(dw, dh) ;
  530.     if (win) ChangeWindowBox(win, left, top, width, height) ;
  531. }
  532.  
  533. void window::box(short x, short y, short w, short h)
  534. {
  535.     rectangle::box(x, y, w, h) ;
  536.     if (win) ChangeWindowBox(win, left, top, width, height) ;
  537. }
  538.  
  539. void window::limits(short wmin, short hmin, short wmax, short hmax)
  540. {
  541.     rectangle::limits(wmin, hmin, wmax, hmax) ;
  542.     if (win) WindowLimits(win, minw, minh, maxw, maxh) ;
  543. }
  544. void window::pmove(long x, long y)                     // Move(rp, ...)
  545. {
  546.     Move(rp, x, y) ;
  547. }
  548.  
  549. void window::text( const char *string, unsigned long count )
  550. {
  551.     Text(rp, STRPTR(string), count) ;
  552. }
  553.  
  554. void window::otext( long x, long y, const char *string )
  555. {
  556.     pmove(x, y) ;
  557.     text(string, strlen(string)) ;
  558. }
  559.  
  560. void window::fname(gadget *g, unsigned long classe, unsigned short code)
  561. {
  562.     strcpy(sname, ((string *)g)->curstring) ;
  563. }
  564.  
  565. #if defined( __GNUG__ )
  566. ADD2INIT(_STI_4500_initouicat, -40);
  567. ADD2INIT(_STI_4500_initwinlist, -40);
  568. ADD2EXIT(_STD_4500_closeouicat,-40);
  569. ADD2EXIT(_STD_4500_closewinlist,-40);
  570. #endif
  571.