- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
451 lines
15 KiB
C++
451 lines
15 KiB
C++
// (C) Copyright 1994 by Borland International
|
|
//
|
|
// DragDrop.c - Drag and Drop example in C
|
|
|
|
// Beginning of file dragdrop.c
|
|
|
|
/* --------------------------------------------------------------
|
|
This is a code example using the Drag and Drop feature in
|
|
Windows 3.1 with C. The example shows how to drop files
|
|
into the client area of the main window and then print out
|
|
the file names only if they were dropped in the client area.
|
|
The list of files will be kept in a linked list of structures.
|
|
The code is well commented with Steps to follow the creation
|
|
of the application as well as comments for common pitfalls
|
|
and important lines of code that affect the performance of
|
|
your application.
|
|
--------------------------------------------------------------- */
|
|
|
|
char HelpText[]=
|
|
"\n\rThis application must be run under Windows 3.1 or greater.\n\r \
|
|
Bring up the File Manager or an equivalent file viewer.\n\r \
|
|
Select a file with the left mouse button and keep the button down.\n\r \
|
|
Now drag the mouse over until it is on top of the drag\n\r \
|
|
n' drop window client area. Now release the left mouse\n\r \
|
|
button. You have just dragged and dropped a file. To\n\r \
|
|
drag a group of files, select the group with the Shift\n\r \
|
|
and arrow keys and then repeat the previous directions.";
|
|
|
|
#define STRICT // define STRICT to provide maximum type safety
|
|
// as defined by Microsoft
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
#include <string.h>
|
|
#include <alloc.h>
|
|
#include <windowsx.h>
|
|
/***************************************************************
|
|
Step 0:
|
|
This is the header file which declares the Drag and Drop
|
|
functions. The functions are in SHELL.DLL
|
|
****************************************************************/
|
|
#include <shellapi.h>
|
|
|
|
LRESULT FAR PASCAL _export MainWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
void AddFiles(HWND, struct List*);
|
|
|
|
// Definition of structure types for Linked list of files
|
|
struct FileList {
|
|
char *lpFileName; // Name of dragged file
|
|
int x, y; // Position in client area dropped
|
|
BOOL inClient; // Dropped in client Flag
|
|
struct FileList *Next; // Points to next file in group dragged
|
|
};
|
|
struct List {
|
|
struct List *Next; // Points to next node in List
|
|
struct FileList *FLptr; // Points to Filelist(s)
|
|
};
|
|
|
|
// Global variables
|
|
HINSTANCE hInst; // current instance
|
|
struct List *liAllFiles; // Pointer to main list of files
|
|
BOOL GetHelp;
|
|
|
|
|
|
/********************************************************************/
|
|
void FileDrop( struct FileList* ptr, char *FileName , int px, int py,
|
|
BOOL inClientarea )
|
|
{
|
|
ptr->lpFileName =(char*)malloc(strlen( FileName ) + 1 );
|
|
strcpy( ptr->lpFileName, FileName );
|
|
ptr->x = px;
|
|
ptr->y = py;
|
|
ptr->inClient = inClientarea;
|
|
ptr->Next=NULL;
|
|
}
|
|
|
|
char *WhoAmI(struct FileList *ptr)
|
|
{
|
|
static char buffer[ 80 ];
|
|
|
|
wsprintf( buffer, "File: %s [ %d , %d ] inClient: %d",
|
|
(LPSTR)ptr->lpFileName, ptr->x , ptr->y, ptr->inClient );
|
|
|
|
//WARNING!!: Serious problem recognized:
|
|
//In the small model, without the typecast,
|
|
//lpFileName was two bytes on the stack of which
|
|
//wsprintf took 4.
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|
|
void WMDropFiles( WPARAM WParam, HWND hWnd)
|
|
/*********************************************************
|
|
Step 3:
|
|
Retrieve a handle to an internal data structure in
|
|
SHELL.DLL. Get the info of the files out of it.
|
|
**********************************************************/
|
|
{
|
|
struct FileList *FLptr, *FLCurrent=NULL, *FLHead=NULL;
|
|
struct List *liFiles;
|
|
int TotalNumberOfFiles;
|
|
int nFileLength;
|
|
char *pszFileName;
|
|
POINT pPoint;
|
|
BOOL inClientArea;
|
|
int i;
|
|
/********************************************************
|
|
Step 4:
|
|
Identify the handle
|
|
*********************************************************/
|
|
HANDLE Handle = (HANDLE)WParam;
|
|
//WParam contains the Handle to the
|
|
//internal data structure which has
|
|
//information about the dropped file(s)
|
|
|
|
/****************************************************************
|
|
Step 5:
|
|
Find out total number of files dropped, by passing -1 for
|
|
the index parameter to DragQueryFile
|
|
*****************************************************************/
|
|
TotalNumberOfFiles = DragQueryFile( Handle , -1, NULL, 0 );
|
|
GetHelp=FALSE;
|
|
|
|
liFiles =(struct List*)malloc(sizeof(struct List));
|
|
|
|
for ( i = 0; i < TotalNumberOfFiles ; i++ )
|
|
{
|
|
/************************************************************
|
|
Step 6:
|
|
Get the length of a filename by telling DragQueryFile
|
|
which file your querying about ( i ), and passing NULL
|
|
for the buffer parameter.
|
|
*************************************************************/
|
|
nFileLength = DragQueryFile( Handle , i , NULL, 0 );
|
|
pszFileName = (char*)malloc(nFileLength + 1);
|
|
|
|
/************************************************************
|
|
Step 7:
|
|
Copy a file name. Tell DragQueryFile the file
|
|
your interested in (i) and the length of your buffer.
|
|
NOTE: Make sure that the length is 1 more then the filename
|
|
to make room for the null charater!
|
|
*************************************************************/
|
|
DragQueryFile( Handle , i, pszFileName, nFileLength + 1 );
|
|
//copies over the filename
|
|
|
|
|
|
/**************************************************************
|
|
Step 8:
|
|
Getting the file dropped. The location is relative to your
|
|
client coordinates, and will have negative values if dropped
|
|
in the non client parts of the window.
|
|
|
|
DragQueryPoint copies that point where the file was dropped
|
|
and returns whether or not the point is in the client area.
|
|
Regardless of whether or not the file is dropped in the client
|
|
or non-client area of the window, you will still receive the
|
|
file name.
|
|
***************************************************************/
|
|
|
|
inClientArea = DragQueryPoint( Handle , &pPoint );
|
|
FLptr= (struct FileList*)malloc(sizeof(struct FileList));
|
|
if(FLHead == NULL)
|
|
FLHead = FLptr;
|
|
|
|
FileDrop(FLptr, pszFileName , pPoint.x, pPoint.y , inClientArea );
|
|
|
|
// Add new struct to FileList structure list
|
|
if(FLHead != FLptr)
|
|
{
|
|
FLCurrent->Next=FLptr;
|
|
FLCurrent=FLptr;
|
|
FLptr->Next=NULL;
|
|
}
|
|
else
|
|
{
|
|
FLHead->Next=NULL;
|
|
FLCurrent = FLHead;
|
|
}
|
|
}
|
|
liFiles->FLptr=FLHead; // Point to first FileList struct in list
|
|
AddFiles( hWnd, (struct List*)liFiles ); //Add this sublist of dropped files
|
|
//to the big list.
|
|
/************************************************************
|
|
Step 9:
|
|
Release the memory shell allocated for this handle
|
|
with DragFinish.
|
|
NOTE: This is a real easy step to forget and could
|
|
explain memory leaks and incorrect program performance.
|
|
*************************************************************/
|
|
DragFinish( Handle );
|
|
}
|
|
|
|
/************************************************************/
|
|
void AddFiles( HWND hWnd, struct List *pliFiles )
|
|
{
|
|
if(liAllFiles==NULL)
|
|
{
|
|
liAllFiles=pliFiles;
|
|
liAllFiles->Next=NULL;
|
|
}
|
|
else
|
|
{
|
|
pliFiles->Next=liAllFiles; // Put at front of list
|
|
liAllFiles=pliFiles;
|
|
}
|
|
InvalidateRect( hWnd, NULL, TRUE );
|
|
UpdateWindow( hWnd );
|
|
}
|
|
|
|
/************************************************************
|
|
Delete FileList structures on linked list
|
|
*************************************************************/
|
|
void deleteFileList( struct FileList *pFList)
|
|
{
|
|
if(pFList->Next != NULL)
|
|
deleteFileList(pFList->Next); // Recursion - delete next FileList struct
|
|
free(pFList->lpFileName); // free string allocation
|
|
free(pFList); // free structure FileList
|
|
}
|
|
|
|
/************************************************************
|
|
Delete List structures on linked list
|
|
*************************************************************/
|
|
void deleteList( struct List *pliFiles)
|
|
{
|
|
if(pliFiles != NULL)
|
|
{
|
|
if(pliFiles->Next != NULL)
|
|
deleteList(pliFiles->Next); // Recursion - delete next List struct
|
|
if(pliFiles->FLptr != NULL)
|
|
deleteFileList(pliFiles->FLptr);// Initial call to free FileList
|
|
free(pliFiles); // free List struct
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************/
|
|
BOOL InitApplication(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
// Fill in window class structure with parameters that describe the
|
|
// main window.
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
|
|
wc.lpfnWndProc = (LRESULT (FAR PASCAL*)())MainWndProc; // Function to retrieve messages for
|
|
// windows of this class.
|
|
wc.cbClsExtra = 0; // No per-class extra data.
|
|
wc.cbWndExtra = 0; // No per-window extra data.
|
|
wc.hInstance = hInstance; // Application that owns the class.
|
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
|
|
wc.lpszMenuName = "DRAGDROPMENU";
|
|
wc.lpszClassName = "DragnDrop"; // Name used in call to CreateWindow.
|
|
|
|
/* Register the window class and return success/failure code. */
|
|
|
|
return (RegisterClass(&wc));
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
HWND hWnd; // Main window handle.
|
|
|
|
/* Save the instance handle in static variable, which will be used in */
|
|
/* many subsequence calls from this application to Windows. */
|
|
|
|
hInst = hInstance;
|
|
|
|
/* Create a main window for this application instance. */
|
|
|
|
hWnd = CreateWindow(
|
|
"DragnDrop", // See RegisterClass() call.
|
|
"Drag & Drop Example", // Text for window title bar.
|
|
WS_OVERLAPPEDWINDOW, // Window style.
|
|
CW_USEDEFAULT, // Default horizontal position.
|
|
CW_USEDEFAULT, // Default vertical position.
|
|
CW_USEDEFAULT, // Default width.
|
|
CW_USEDEFAULT, // Default height.
|
|
NULL, // Overlapped windows have no parent.
|
|
NULL, // Use the window class menu.
|
|
hInstance, // This instance owns this window.
|
|
NULL // Pointer not needed.
|
|
);
|
|
|
|
/* If window could not be created, return "failure" */
|
|
|
|
if (!hWnd)
|
|
return (FALSE);
|
|
|
|
/* Make the window visible; update its client area; and return "success" */
|
|
|
|
ShowWindow(hWnd, nCmdShow); // Show the window
|
|
UpdateWindow(hWnd); // Sends WM_PAINT message
|
|
return (TRUE); // Returns the value from PostQuitMessage
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
|
|
****************************************************************************/
|
|
LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc; // HDC for Window
|
|
PAINTSTRUCT ps; // Paint Struct for BeginPaint call
|
|
RECT rect;
|
|
struct List* Ltemp;
|
|
struct FileList* FLtemp;
|
|
char *bufstring;
|
|
int i;
|
|
|
|
switch (message) {
|
|
case WM_CREATE: // Initialize Global vars
|
|
GetHelp=TRUE;
|
|
/************************************************************
|
|
liAllFiles is a pointer to a linked list of structure
|
|
List. Each List in the linked list will contain the file
|
|
names that were received during a WM_DROPFILES messages
|
|
and will be stored in a linked list of structure FileList.
|
|
*************************************************************/
|
|
liAllFiles=NULL;
|
|
|
|
/****************************************************************
|
|
Step 1:
|
|
calling DragAcceptFiles. If you pass FALSE, you're saying
|
|
I don't accept them anymore.
|
|
*****************************************************************/
|
|
DragAcceptFiles( hWnd , TRUE );
|
|
|
|
return 0L;
|
|
case WM_DROPFILES:
|
|
/************************************************************
|
|
Step 2:
|
|
Make call to WMDropFiles
|
|
*************************************************************/
|
|
WMDropFiles(wParam, hWnd);
|
|
break;
|
|
case WM_PAINT:
|
|
// Display the file name(s)
|
|
hdc=BeginPaint(hWnd,&ps);
|
|
if(GetHelp)
|
|
{
|
|
GetClientRect(hWnd,&rect);
|
|
DrawText(hdc,HelpText,strlen(HelpText),&rect,DT_CENTER|DT_WORDBREAK);
|
|
}
|
|
else
|
|
{
|
|
SetBkMode ( hdc , TRANSPARENT );
|
|
Ltemp=liAllFiles;
|
|
|
|
i=0;
|
|
while ( Ltemp != NULL )
|
|
{
|
|
FLtemp=Ltemp->FLptr;
|
|
while( FLtemp != NULL )
|
|
{
|
|
bufstring = WhoAmI(FLtemp);
|
|
TextOut( hdc, 10, 20 * i++, bufstring, strlen(bufstring));
|
|
FLtemp=FLtemp->Next;
|
|
}
|
|
i++;
|
|
Ltemp=Ltemp->Next;
|
|
}
|
|
}
|
|
EndPaint(hWnd,&ps);
|
|
break;
|
|
case WM_COMMAND: // message: command from application menu
|
|
switch(GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case 101:
|
|
GetHelp=TRUE;
|
|
InvalidateRect(hWnd,NULL,TRUE);
|
|
UpdateWindow(hWnd);
|
|
break;
|
|
case 102:
|
|
GetHelp=FALSE;
|
|
InvalidateRect(hWnd,NULL,TRUE);
|
|
UpdateWindow(hWnd);
|
|
break;
|
|
case 103:
|
|
GetHelp=FALSE;
|
|
deleteList(liAllFiles);
|
|
liAllFiles=NULL;
|
|
InvalidateRect(hWnd,NULL,TRUE);
|
|
UpdateWindow(hWnd);
|
|
break;
|
|
case 104:
|
|
MessageBox(hWnd,"DRAG n' DROP Example\nCopyright (c) 1994 Borland International, Inc.","ABOUT BOX",MB_OK);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case WM_CLOSE:
|
|
/****************************************************************
|
|
Step 10:
|
|
Don't accept files anymore
|
|
*****************************************************************/
|
|
DragAcceptFiles( hWnd , FALSE );
|
|
|
|
deleteList(liAllFiles);
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
case WM_QUIT:
|
|
case WM_DESTROY: // message: window being destroyed
|
|
PostQuitMessage(0);
|
|
break;
|
|
default: // Passes it on if unproccessed
|
|
return (DefWindowProc(hWnd, message, wParam, lParam));
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
#pragma argsused
|
|
/**************************************************************/
|
|
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
MSG msg; // message
|
|
if (!hPrevInstance) // Other instances of app running?
|
|
if (!InitApplication(hInstance)) // Initialize shared things
|
|
return (FALSE); // Exits if unable to initialize
|
|
|
|
/* Perform initializations that apply to a specific instance */
|
|
|
|
if (!InitInstance(hInstance, nCmdShow))
|
|
return (FALSE);
|
|
|
|
/* Acquire and dispatch messages until a WM_QUIT message is received. */
|
|
|
|
while (GetMessage(&msg, // message structure
|
|
NULL, // handle of window receiving the message
|
|
0, // lowest message to examine
|
|
0)) // highest message to examine
|
|
{
|
|
TranslateMessage(&msg); // Translates virtual key codes
|
|
DispatchMessage(&msg); // Dispatches message to window
|
|
}
|
|
return (msg.wParam); // Returns the value from PostQuitMessage
|
|
}
|
|
|
|
// end of file dragdrop.c
|