KeymapSwitcher: docky.c

// DOCKY.C
//#define DDEBUG
 
#include "dockybase.h"
 
#include <proto/intuition.h>
#include <proto/datatypes.h>
#include <proto/graphics.h>
#include <proto/Picasso96API.h>
#include <workbench/icon.h>
#include <classes/popupmenu.h>
#include <classes/requester.h>
#include <images/bitmap.h>
#include <graphics/composite.h>
 
#include "KeyMapSwitcher_rev.h"
 
extern struct ExecIFace *IExec;
extern struct UtilityIFace *IUtility;
extern struct IntuitionIFace *IIntuition;
extern struct IconIFace *IIcon;
extern struct DataTypesIFace *IDataTypes;
extern struct DOSIFace *IDOS;
extern struct GraphicsIFace *IGraphics;
extern struct P96IFace *IP96;
 
extern struct TagItem dockyTags[];
extern Object *Objects[LAST_NUM];
 
extern int OpenPrefsWindow(struct DockyData *dd);
extern void OpenDockWindow(struct DockyData *dd);
extern void OpenDockMenu(struct DockyData *dd);
extern void SetKeyMapFlag(char *keymapname, char *keymapflag);
extern void ChangeKeymap(struct DockyData *dd, STRPTR keymap);
extern void ReadInputPrefsKeymap(STRPTR keymap);
 
void SignalDocky(struct DockyData *dd, uint32 flags);
 
BOOL DockySClick = FALSE, WinMode = FALSE;
char keymap1Flag[1024] = "", keymap2Flag[1024] = "";
Object *picObject = NULL;
 
 
uint32 _docky_Obtain(struct DockyIFace *Self)
{
#ifdef DDEBUG
IExec->DebugPrintF("[%s]docky_Obtain\n",LIBNAME);
#endif
 Self->Data.RefCount++;
 return Self->Data.RefCount;
}
 
 
void LoadImageFlag(struct DockyData *dd)
{
 char keymapflag[64];
#ifdef DDEBUG
IDOS->Printf("keymapSel='%s' Loading flag image...\n",dd->keymapSel);
#endif
 if(IUtility->Stricmp(dd->keymap2Name, dd->keymapSel) == 0)
  IUtility->Strlcpy( keymapflag, keymap2Flag, sizeof(keymapflag) );
 else IUtility->Strlcpy( keymapflag, keymap1Flag, sizeof(keymapflag) );
/*
 picObject = IIntuition->NewObject(NULL, "bitmap.image",
                                     BITMAP_SourceFile, keymapflag,
                                     BITMAP_Screen,     dd->scr,
                                     //BITMAP_Precision, PRECISION_IMAGE,
                                     BITMAP_Masking,    TRUE,
                                     BITMAP_Transparent, TRUE,
                                    TAG_DONE);
*/
 picObject = IDataTypes->NewDTObject(keymapflag,
                                     PDTA_Screen, dd->scr,
                                     PDTA_DestMode, PMODE_V43,
                                     DTA_GroupID, GID_PICTURE,
                                    TAG_DONE);
 
}
 
 
void DockyRender(struct DockyData *dd)
{
 struct BitMap *tempBM = NULL;
 LONG lock;
 struct RenderInfo ri;
 
 tempBM = IP96->p96AllocBitMap(25, 18, 32, 0L, NULL, RGBFB_A8R8G8B8);
#ifdef DDEBUG
IDOS->Printf("tempBM=0x%08lx\n",tempBM);
#endif
 if( (lock = IP96->p96LockBitMap( tempBM, (UBYTE *)&ri, sizeof(ri) )) )
 {// to pass the Alpha info from the DT object to the memory (RenderInfo) of the bitmap
 IIntuition->IDoMethod(picObject, PDTM_READPIXELARRAY,ri.Memory,
                                  PBPAFMT_ARGB,ri.BytesPerRow, 0, 0, 25, 18);
#ifdef DDEBUG
IDOS->Printf("[0x%08lx]ri.Memory=0x%08lx   ri.BytesPerRow=%ld\n",ri,ri.Memory,ri.BytesPerRow);
#endif
// IDataTypes->DisposeDTObject(picObject);
// picObject = NULL;
 IP96->p96UnlockBitMap(tempBM, lock);
 }
 
// if(picObject)
// {
//  IDataTypes->DisposeDTObject(picObject);
//  picObject = NULL;
// }
 
 IGraphics->CompositeTags(COMPOSITE_Src_Over_Dest, tempBM, dd->rp->BitMap,
                          //COMPTAG_SrcWidth, 25,
                          //COMPTAG_SrcHeight, 18,
                          //COMPTAG_SrcX, 0,
                          //COMPTAG_SrcY, 0,
                          //COMPTAG_OffsetX, 0,
                          //COMPTAG_OffsetY, 0,
                         TAG_DONE);
 
 IP96->p96FreeBitMap(tempBM);
 tempBM = NULL;
}
 
 
uint32 _docky_Release(struct DockyIFace *Self)
{
#ifdef DDEBUG
IExec->DebugPrintF("[%s]docky_Release\n",LIBNAME);
#endif
 Self->Data.RefCount--;
 if( !Self->Data.RefCount && (Self->Data.Flags & IFLF_CLONED) )
 {
  IExec->DeleteInterface( (struct Interface *)Self );
  return 0;
 }
 
 return Self->Data.RefCount;
}
 
 
struct DockyIFace *_docky_Clone(struct DockyIFace *Self)
{
 struct DockyIFace *docky;
#ifdef DDEBUG
IExec->DebugPrintF("[%s]docky_Clone\n",LIBNAME);
#endif
 docky = (struct DockyIFace *)IExec->MakeInterface(Self->Data.LibBase, dockyTags);
 if(docky)
 {
  struct DockyData *dd = (struct DockyData *)((uint32)docky - docky->Data.NegativeSize);
 
  docky->Data.Flags |= IFLF_CLONED;
 
  IUtility->ClearMem( dd, sizeof(struct DockyData) );
 
  dd->size.width = 25; // width of flag images
  dd->size.height = 18; // height of flag images
 
  ReadInputPrefsKeymap(dd->keymap1Name);
 }
 
 return docky;
}
 
 
static void ReadDockyPrefs(struct DockyData *dd)
{
 struct DiskObject *micon;
 STRPTR ttp;
#ifdef DDEBUG
IExec->DebugPrintF("[%s]ReadDockyPrefs\n",LIBNAME);
#endif
 micon = IIcon->GetDiskObjectNew(dd->filename);
 if(micon)
 {
  ttp = IIcon->FindToolType(micon->do_ToolTypes, "KEYMAP2");
  if(ttp) IUtility->Strlcat( dd->keymap2Name, ttp, sizeof(dd->keymap2Name) );
 
  ttp = IIcon->FindToolType(micon->do_ToolTypes, "DOCKY_1CLICK");
  if(ttp) DockySClick = ( IIcon->MatchToolValue(ttp, "YES") | IIcon->MatchToolValue(ttp, "ON") );
 
  ttp = IIcon->FindToolType(micon->do_ToolTypes, "MODE");
  if(ttp) WinMode = IIcon->MatchToolValue(ttp, "WIN");
 
 }
 IIcon->FreeDiskObject(micon);
 
 IUtility->Strlcpy( dd->keymapSel, dd->keymap1Name, sizeof(dd->keymapSel) ); // default keymap selected
#ifdef DDEBUG
IDOS->Printf("DOCKY_1CLICK=%ld\n",DockySClick);
#endif
 // language 1: input.prefs; keymap1Name & keymap1Flag
 SetKeyMapFlag(dd->keymap1Name, keymap1Flag);
#ifdef DDEBUG
IDOS->Printf("KEYMAP1='%s' FLAG1='%s' (input.prefs)\n",dd->keymap1Name,keymap1Flag);
#endif
 // language 2: tooltype (KEYMAP2); keymap2Name & keymap2Flag
 SetKeyMapFlag(dd->keymap2Name, keymap2Flag);
#ifdef DDEBUG
IDOS->Printf("KEYMAP2='%s' FLAG2='%s' (tooltype)\n",dd->keymap2Name,keymap2Flag);
#endif
}
 
 
void _docky_Expunge(struct DockyIFace *Self)
{
 struct DockyData *dd = (struct DockyData *)((uint32)Self - Self->Data.NegativeSize);
#ifdef DDEBUG
IExec->DebugPrintF("[%s]docky_Expunge\n",LIBNAME);
#endif
 if(!Self->Data.RefCount)
 {
#ifdef DDEBUG
IDOS->Printf("Reseting to Input Prefs. keymap ('%s')\n",dd->keymap1Name);
#endif
  ChangeKeymap(dd, dd->keymap1Name); // reset default input keymap
#ifdef DDEBUG
IDOS->Printf("Disposing picObject=0x%08lx\n",picObject);
#endif
  if(picObject) IDataTypes->DisposeDTObject(picObject);
  picObject = NULL;
 }
 
}
 
 
BOOL _docky_DockyGet(struct DockyIFace *Self, uint32 msgType, uint32 *msgData)
{
 struct DockyData *dd = (struct DockyData *)((uint32)Self - Self->Data.NegativeSize);
 BOOL res = TRUE;
#ifdef DDEBUG
IExec->DebugPrintF("[%s]DockyGet\n",LIBNAME);
//IDOS->Printf("  %02ld\n",msgType);
#endif
 switch(msgType)
 {
  case DOCKYGET_Version:
   *msgData = DOCKYVERSION;
  break;
 
  case DOCKYGET_GetSize:
   *((struct DockySize *)msgData) = dd->size;
  break;
 
  case DOCKYGET_FrameDelay:
   *msgData = -1;
  break;
 
  case DOCKYGET_RenderMode:
   *msgData = DOCKYRENDERMODE_RPPA;
  break;
 
//  case DOCKYGET_AllowsIconChange:
//   *msgData = FALSE;
//  break;
 
  case DOCKYGET_Notifications:
   *msgData = DOCKYNOTIFY_MOUSEBUTTONS;
  break;
 
  case DOCKYGET_ContextMenu:
  {
   Object *contextMenu = (Object *)msgData;
#ifdef DDEBUG
IDOS->Printf("[DOCKYGET_ContextMenu]\n");
#endif
/*   Object *item1 = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                PMIA_Title,    dd->keymap1Name,
                                PMIA_ID,       MENU_OPT1,
                                PMIA_Disabled, TRUE,
                                //PMIA_ReadOnly, TRUE,
                                PMIA_Icon, OBJ(GID_BITMAP1) = IIntuition->NewObject(NULL, "bitmap.image",
                                     BITMAP_SourceFile, keymap1Flag,
                                     BITMAP_Screen,     dd->scr,
                                     BITMAP_Masking,    TRUE,
                                    TAG_DONE),
                               TAG_END);
 
   Object *item2 = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                PMIA_Title,    dd->keymap2Name,
                                PMIA_ID,       MENU_OPT2,
                                PMIA_Disabled, TRUE,
                                //PMIA_ReadOnly, TRUE,
                                PMIA_Icon, OBJ(GID_BITMAP2) = IIntuition->NewObject(NULL, "bitmap.image",
                                     BITMAP_SourceFile, keymap2Flag,
                                     BITMAP_Screen,     dd->scr,
                                     BITMAP_Masking,    TRUE,
                                    TAG_DONE),
                               TAG_END);
*/
   Object *subMenu = IIntuition->NewObject(NULL, "popupmenu.class", TAG_END);
 
   Object *itemSM = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                 PMIA_Title,   "Mode",
                                 PMIA_SubMenu, subMenu,
                                TAG_END);
 
   Object *itemS1 = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                 PMIA_Title,   "PopUp",
                                 PMIA_ID,      MENU_OPT1,
                                 PMIA_CheckIt, TRUE,
                                 PMIA_Checked, !WinMode,
                                TAG_END);
 
   Object *itemS2 = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                 PMIA_Title,   "Window",
                                 PMIA_ID,      MENU_OPT2,
                                 PMIA_CheckIt, TRUE,
                                 PMIA_Checked, WinMode,
                                TAG_END);
 
   Object *item3 = IIntuition->NewObject(NULL, "popupmenuitem.class",
                                PMIA_Title, "Settings...",
                                PMIA_ID,    MENU_PREFS,
                               TAG_END);
 
//   Object *itemBar = IIntuition->NewObject(NULL, "popupmenuitem.class", PMIA_Title,~0, TAG_END);
 
  // language2 valid/available
//  if( !OBJ(GID_BITMAP2) ) IIntuition->SetAttrs(item2, PMIA_Disabled,FALSE, PMIA_ReadOnly,TRUE, TAG_DONE);
 
   IIntuition->IDoMethod(subMenu, OM_ADDMEMBER, itemS1); // mode popup
   IIntuition->IDoMethod(subMenu, OM_ADDMEMBER, itemS2); // mode window
   IIntuition->IDoMethod(contextMenu, OM_ADDMEMBER, itemSM); // Submenu string 'Mode'
   if(WinMode) IIntuition->IDoMethod(contextMenu, OM_ADDMEMBER, item3); // Settings...
//   IIntuition->IDoMethod(contextMenu, OM_ADDMEMBER, itemBar);
  }
  break;
 
//  case DOCKYGET_AllowsRename:
//   *msgData = FALSE;
//  break;
 
  case DOCKYGET_InvisibleProcess:
   *msgData = FALSE;
  break;
 
  case DOCKYGET_ShowsName:
   *msgData = TRUE;
  break;
 
//  case DOCKYGET_Name:
//   *msgData = (uint32)IDOS->FilePart(dd->filename);
//  break;
 
  case DOCKYGET_NeedsAttention: // uint32 BOOL
#ifdef DDEBUG
IDOS->Printf("[DOCKYGET_NeedsAttention]\n");
#endif
   *msgData  = TRUE;
  break;
 
  default:
#ifdef DDEBUG
IDOS->Printf("[DOCKYGET_????] %02ld\n",msgType);
#endif
   res = FALSE;
  break;
 }
 
 return res;
}
 
 
BOOL _docky_DockySet(struct DockyIFace *Self, uint32 msgType, uint32 msgData)
{
 struct DockyData *dd = (struct DockyData *)((uint32)Self - Self->Data.NegativeSize);
 BOOL res = TRUE;
#ifdef DDEBUG
IExec->DebugPrintF("[%s]DockySet\n",LIBNAME);
//IDOS->Printf("%04ld\n",msgType);
#endif
 switch(msgType)
 {
  case DOCKYSET_FileName:
   IUtility->Strlcpy( dd->filename, (STRPTR)msgData, sizeof(dd->filename) );
   ReadDockyPrefs(dd);
  break;
 
  case DOCKYSET_Screen:
   dd->scr = (struct Screen *)msgData;
   LoadImageFlag(dd);
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_Screen]\n");
#endif
 break;
 
  case DOCKYSET_Window:
   dd->win = (struct Window *)msgData;
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_Window]\n");
#endif
  break;
 
  case DOCKYSET_RenderDestination:
  {
   struct DockyRenderDestination *drd = (struct DockyRenderDestination *)msgData;
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_RenderDestination] ");
#endif
   dd->size = drd->renderSize;
 
   switch(drd->renderMode)
   {
    case DOCKYRENDERMODE_RPPA:
#ifdef DDEBUG
IDOS->Printf("DOCKYRENDERMODE_RPPA\n");
#endif
     dd->rp = drd->render.RP;
    break;
    default:
#ifdef DDEBUG
IDOS->Printf("default\n");
#endif
     dd->rp = NULL;
     res = FALSE;
    break;
   }
 
  }
  break;
 
  case DOCKYSET_RedrawNow:
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_RedrawNow]\n");
#endif
//   LoadImageFlag(dd); <- DON'T! Freezes system if drag an icon over docky
   DockyRender(dd);
  break;
 
  case DOCKYSET_DockTypeChange:
  {
   struct DockyDockType *ddt = (struct DockyDockType *)msgData;
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_DockTypeChange]\n");
#endif
   if(dd->self.dockNr == ddt->dockNr && ddt->dockType != AMIDOCK_DockType_Icons)
    res = FALSE;
  }
  break;
 
  case DOCKYSET_SingleClick:
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_SingleClick]\n");
#endif
   if(!DockySClick) break;
  case DOCKYSET_DoubleClick:
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_DoubleClick]\n");
#endif
   if(WinMode) OpenDockWindow(dd);
   else OpenDockMenu(dd);
   LoadImageFlag(dd); // (re)load new image/flag after user choosed new
   SignalDocky(dd, 0); // we only need to 'RedrawNow': just send IExec->Signal...
  break;
 
  case DOCKYSET_ContextMenuResult:
  {
   Object *o = (Object *)msgData;
#ifdef DOCKY_DEBUG
IDOS->Printf("[DOCKYSET_ContextMenuResult]\n");
#endif
   if(o)
   {
    IIntuition->GetAttr(PMIA_ID, o, (uint32 *)&dd->km_item);
#ifdef DDEBUG
IDOS->Printf("KeyMapSwitcher: item=%ld\n",dd->km_item);
#endif
    switch(dd->km_item)
    {
     case MENU_OPT1: WinMode = FALSE; // PopUp mode
     break;
     case MENU_OPT2: WinMode = TRUE; // Window mode
     break;
     case MENU_PREFS:
     {
      char keymap2Sel[128]; // to check if keymap2 changed
 
      IUtility->Strlcpy( keymap2Sel, dd->keymap2Name, sizeof(keymap2Sel) );
      OpenPrefsWindow(dd);
#ifdef DDEBUG
IDOS->Printf("%s == %s?\n",dd->keymap2Name,keymap2Sel);
#endif
      if(IUtility->Stricmp(dd->keymap2Name, keymap2Sel) != 0)
      {// NEW keymap2: tooltype (KEYMAP2); keymap2Name & keymap2Flag
       SetKeyMapFlag(dd->keymap2Name, keymap2Flag);
#ifdef DDEBUG
IDOS->Printf("[NEW]KEYMAP2='%s' FLAG2='%s' (tooltype)\n",dd->keymap2Name,keymap2Flag);
#endif
      }
     }
     break;
    } // END switch(dd-km->item)
 
   } // END if(o)..
  }
  break;
 
  case DOCKYSET_DockyAttention:
   dd->attn = *(struct DockyAttention *)msgData;
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_DockyAttention] 0x%08lx %d\n",dd->attn.amidockTask,dd->attn.attentionSignalBit);
#endif
  break;
 
  default:
#ifdef DDEBUG
IDOS->Printf("[DOCKYSET_????] %04ld\n",msgType);
#endif
   res = FALSE;
  break;
 }
 
 return res;
}
 
 
BOOL _docky_DockyProcess(struct DockyIFace *Self, uint32 turnCount, uint32 *msgType,
                         uint32 *msgData, BOOL *anotherTurn)
{
// struct DockyData *dd = (struct DockyData *)((uint32)Self - Self->Data.NegativeSize);
#ifdef DDEBUG
IExec->DebugPrintF("[%s]docky_DockyProcess\n",LIBNAME);
IDOS->Printf("DockyProcess: turnCount=%ld msgType=%ld msgData=%ld anotherTurn=%ld\n",\
              turnCount,*msgType,*msgData,*anotherTurn);
#endif
 
 return TRUE;
}
 
 
void SignalDocky(struct DockyData *dd, uint32 flags)
{
 IExec->Signal( (struct Task *)dd->attn.amidockTask, 1L << dd->attn.attentionSignalBit);
}