Solved

Getting the File List's ListHandle from within CustomGetFile

Posted on 1997-07-08
5
226 Views
Last Modified: 2013-12-26
If I'm in my Dialog hook function, called by CustomGetFile, how can I get the ListHandle for the File list that the Toolbox makes?  I need to be able to see & change which items are selected.
0
Comment
Question by:dhirsch
  • 3
  • 2
5 Comments
 
LVL 1

Expert Comment

by:Paul B
ID: 1291535
Hi,
  Are you apposed to using a patch :/
If you are not I can give you an answer and code example.

Paul B
0
 

Author Comment

by:dhirsch
ID: 1291536
Paul-
  A patch is fine.  I know there's no easy way to get at it, because I've tried all the easy ways.
-Dave
0
 
LVL 1

Accepted Solution

by:
Paul B earned 150 total points
ID: 1291537
Hi,
  Getting this to work is extreamly complicated. But it can be done :)
First the bad news:
The patch itself MUST be in 68K code. The reason for this is that the List Manager uses a pascal dispatched routine selector with a different number of params for each selector.
This makes creating a Universal Proc Pointer to the patch nearly impossible.

If you need this to work for PPC there are work arounds such as having your App in PPC and have the code that patches in a seperate resource compiled for 68K and installing a gestalt or something.
For the sake of time I'll only do that if you need it.
If you do neesd PPC email me and I will send you code for PPC. This will require a little more time.
My email adrress is pbaxter@assistivetech.com

The code is in three functions
PatchLNew    -- installs the patch. Call this right before your call to CustomGetFile
UnPatchLNew  -- removes the patch. Call this right after your call to CustomGetFile
LNewPatch    -- the patch itself --- very scary code

The code needs two global variables
gOldLNew     -- original trap address
gMyListhande -- The list handle that you want;

Here now the patch from hell:

#include <Traps.h>

void PatchLNew(void);
void UnPatchLNew(void);
asm void LNewPatch(void);

#if !GENERATINGPOWERPC
typedef pascal ListRef (*LNewProcPtr) (
      const Rect *rView,
      const ListBounds *dataBounds,
      Point cSize,
      short theProc,
      WindowRef theWindow,
      Boolean drawIt,
      Boolean hasGrow,
      Boolean scrollHoriz,
      Boolean scrollVert);

typedef  LNewProcPtr LNewUPP;

enum {
      uppLNewProcInfo = 0
};

#define NewLNewProc(proc) (LNewUPP)(proc)
#define CallLNewProc(proc, p1, p2, p3, p4, p5, p6, p7, p8, p9)      \
            (* (LNewProcPtr) (proc))(p1, p2, p3, p4, p5, p6, p7, p8, p9)

#else
      #error      only for 68K
#endif

LNewUPP gOldLNew=0;
ListHandle gMyListhande = nil;

void PatchLNew(void)
{
      short trap = _Pack0;
      
      gOldLNew = (LNewUPP)
                  NGetTrapAddress(trap, (trap & 0x0800) ? ToolTrap : OSTrap);

      NSetTrapAddress((UniversalProcPtr) LNewPatch,
                  trap, (trap & 0x0800) ? ToolTrap : OSTrap);

}

void UnPatchLNew(void)
{
      short trap = _Pack0;

      NSetTrapAddress((UniversalProcPtr) gOldLNew,
                  trap, (trap & 0x0800) ? ToolTrap : OSTrap);
      
}

asm void LNewPatch(void)
{
                  bra.s      start

saveA5:            dc.l      0
oldreturn:      dc.l      0
dispatch:      dc.w      0
start:

                  lea            saveA5, a0            // access to globals
                  move.l      a5,(a0)

                  lea            dispatch, a0      // routine selector
                  move.w      4(sp),(a0)
                  move.l      0x0904, a5            // SetCurentA5

                  move.l      gOldLNew, a0      // old trap address
                  lea            dispatch, a1      // get routine selector
                  cmpi.w      #68, (a1)            // LNew selector

                  beq.s      lnewdispatch      // see if we need to steal the result
                  move.l      saveA5,a5            // restore A5
                  jmp            (a0)                  // jump to old address

lnewdispatch:
                  lea            oldreturn,a1      // save return address
                  move.l      (sp),(a1)            

                  lea       restoreA5, a1      // where we want to return to
                  move.l      a1, (sp)            // put6 on stack
                  jmp            (a0)                  // jump to old code
restoreA5:
                  move.l      (sp), gMyListhande      // SAVE THE LIST HANDLE!!!!
                  move.l      saveA5,a5            // restore A5
                  move.l      oldreturn,a1      // get the old return address
                  jmp            (a1)                  // jump!!!
}                  

Paul B
pbaxter@assistivetech.com


0
 

Author Comment

by:dhirsch
ID: 1291538
This looks like what I needed.  I'll email you to discuss PPC implementation, which, sadly, I do need.
0
 
LVL 1

Expert Comment

by:Paul B
ID: 1291539
Hi,
Here is how it is done for PPC with Sample Code.

First the patch should be compiled with 68K and to generate a code resource of type 'patc' with id 0.
Add this resource to your PPC target.

Then main code then calls the patc resource using the Mixed Mode Mgr.

Here is the patch code:
/* File patch.c */
#include <Traps.h>
#include <Gestalt.h>
#include <A4Stuff.h>

#include "patch.h"

asm void LNewPatch(void);
static void PatchLNew(void);
static void UnPatchLNew(void);

static void InstallGlobals(void);
pascal void main(short remove, ListHandle* listaddres);

#if !GENERATINGPOWERPC
typedef pascal ListRef (*LNewProcPtr) (
      const Rect *rView,
      const ListBounds *dataBounds,
      Point cSize,
      short theProc,
      WindowRef theWindow,
      Boolean drawIt,
      Boolean hasGrow,
      Boolean scrollHoriz,
      Boolean scrollVert);

typedef  LNewProcPtr LNewUPP;

enum {
      uppLNewProcInfo = 0
};

#define NewLNewProc(proc) (LNewUPP)(proc)
#define CallLNewProc(proc, p1, p2, p3, p4, p5, p6, p7, p8, p9)      \
            (* (LNewProcPtr) (proc))(p1, p2, p3, p4, p5, p6, p7, p8, p9)

#else
      #error      only for 68K
#endif

LNewUPP gOldLNew=0;
ListHandle *gMyListHandlePtr = nil;


pascal void main(short remove, ListHandle* listaddres)
{
      long oldA4;
      Boolean installfailed;

      oldA4 = SetCurrentA4();

      if (remove) {
            UnPatchLNew();
      }
      else {
            gMyListHandlePtr = listaddres;
            PatchLNew();
            InstallGlobals();      // must be after patch installed!
      }
      SetA4(oldA4);
}

static void PatchLNew(void)
{
      short trap = _Pack0;
      
      gOldLNew = (LNewUPP)
                  NGetTrapAddress(trap, (trap & 0x0800) ? ToolTrap : OSTrap);

      NSetTrapAddress((UniversalProcPtr) LNewPatch,
                  trap, (trap & 0x0800) ? ToolTrap : OSTrap);

}

static void UnPatchLNew(void)
{
      short trap = _Pack0;

      NSetTrapAddress((UniversalProcPtr) gOldLNew,
                  trap, (trap & 0x0800) ? ToolTrap : OSTrap);
      
}



asm void LNewPatch(void)
{
                        bra.s      start

                        entry      static InstallGlobals
InstallGlobals:
                        lea            lstHandAddr, a0
                        move.l      gMyListHandlePtr, (a0)
                        lea            oldAddress, a0
                        move.l      gOldLNew, (a0)
                        rts

lstHandAddr:      dc.l      0
oldAddress:            dc.l      0
oldreturn:            dc.l      0

start:
                        cmpi.w      #68, 4(sp)            // LNew selector
                        beq            DoLNew

                        move.l      oldAddress,a0
                        jmp            (a0)                  // jump to old code

DoLNew:
                        lea            oldreturn,a0      // save return address
                        move.l      (sp),(a0)            

                        lea       Continue, a0      // where we want to return to
                        move.l      a0, (sp)            // put on stack

                        move.l      oldAddress,a0
                        jmp            (a0)                  // jump to old code

Continue:
                        move.l      lstHandAddr,a0
                        move.l      (sp),(a0)

                        move.l      oldreturn,a0      // get the old return address
                        jmp            (a0)                  // jump!!!
}

/* File patch.h */
enum {
      kInstall = 0,
      kRemove = 1
};

Here is the main for PPC
/* File main.c */

#include <StandardFile.h>
#include "patch.h"

void main(void);
void inittoolbox(void);

ListHandle gMyListHandle = nil;
long lasttime = 0;

pascal Boolean HookProc(short itemHit, DialogPtr theDialog, void* data);

enum {
      uppPatchProcInfo = kPascalStackBased
             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ListHandle*)))
};
      
void main(void)
{
      UniversalProcPtr patchCode;
      DlgHookYDUPP dlgHook;
      Handle patchResource;
      StandardFileReply reply;
      long responce;
      OSErr err = noErr;
      Point where;

      inittoolbox();

      patchResource = GetResource('patc', 0);
      if (patchResource) {
            HLock(patchResource);
            HNoPurge(patchResource);
            patchCode = NewRoutineDescriptor((ProcPtr)*patchResource, uppPatchProcInfo,  kM68kISA);
            CallUniversalProc(patchCode, uppPatchProcInfo, kInstall, &gMyListHandle);

            where.h = where.v = -1;

            dlgHook =  NewDlgHookYDProc(HookProc);

            gMyListHandle = nil;
            CustomGetFile(nil, -1, nil, &reply, 0, where, dlgHook, nil, nil, nil, nil);
            gMyListHandle = nil;

            CallUniversalProc(patchCode, uppPatchProcInfo, kRemove, &gMyListHandle);
            DisposeRoutineDescriptor(patchCode);
            
      }
      else {
            SysBeep(1);
      }
}

pascal Boolean HookProc(short itemHit, DialogPtr theDialog, void* data)
{
      Cell thecell, nextcell;
      Boolean result;

      if (gMyListHandle) {
            if (TickCount() - lasttime > 30) {
                  if ((itemHit == 100)) {
                        thecell.h = thecell.v = 0;
                        result = LGetSelect(true, &thecell, gMyListHandle);
                        if (result) {
                              nextcell = thecell;
                              result = LNextCell(false, true, &nextcell, gMyListHandle);
                              LSetSelect(false, thecell, gMyListHandle);
                              LSetSelect(true, nextcell, gMyListHandle);
                        }
                        else {
                              LSetSelect(false, thecell, gMyListHandle);
                              thecell.h = thecell.v = 0;
                              LSetSelect(true, thecell, gMyListHandle);
                        }
                        LAutoScroll(gMyListHandle);
                  }
                  lasttime = TickCount();
            }
      }
      if ((itemHit == ok) || (itemHit == cancel))
            return true;
      return false;
}

void inittoolbox(void)
{
      InitGraf(&qd.thePort);
      FlushEvents ( everyEvent, 0);
      InitFonts();
      InitWindows();
      InitMenus();
      TEInit();
      InitDialogs(nil);
      InitCursor();
}



0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
function returning CString in a regular win32 DLL 8 190
C++ BOOL WINAPI ReadFile fails on windows 10 when reading from USB cable 9 474
notReplace  challenge 53 142
bigDiff challenge 17 126
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question