- List all opened .cpp or .h files
-
This script assigns shortcut which show list of all currently opened .h or .cpp files.
When selecting an item from this list, it will bring the corresponding window to the top.
import IDE;
import editor;
declare kbd = IDE.KeyboardManager.GetKeyboard("Editor");
// Choose a key combination
kbd.Assign("<Alt-F11>","get_h();");
kbd.Assign("<Alt-F12>","get_cpp();");
ChooseFile(ext)
{
declare buffersArray = new array [];
declare i = 0;
declare firstBuffer = editor.TopBuffer;
if( firstBuffer == NULL || !initialized(firstBuffer) ){
print "First Buffer invalid";
return;
}
declare current = firstBuffer;
do {
if( current.TopView != NULL){
declare currExt = new String(current.Extension);
currExt.Upper();
if( currExt.Text == ext.Text ){
buffersArray[i] = current.FullName;
i++;
}
}
current = current.NextBuffer(false);
} while( firstBuffer.FullName != current.FullName );
if( i == 0 ){
print "No modules";
return;
}
declare popup = new PopupMenu(200, 100, buffersArray);
declare res = popup.Track();
if( res == "" ) return;
current = firstBuffer;
for( declare j=0 ; ; current = current.NextBuffer(false),j++ ){
if( current.FullName == res ){
current.TopView.Window.IsHidden = false;
current.TopView.Window.Activate();
break;
}
}
}
get_cpp()
{
declare ext = new String(".CPP");
ChooseFile(ext);
}
get_h()
{
declare ext = new String(".H");
ChooseFile(ext);
}
Download ShowHCpp.zip
- Save editor files on build and make
- This script performs saving of all editor files when build or make is started.
It's purpose is to prevent loss of unsaved files if the IDE crashes during compilation.
print ("SaveOnCompile.spp");
import IDE;
import debugger;
on IDE:>BuildStarted()
{
print ("Saving all...");
IDE.FileSaveAll();
pass();
}
on IDE:>MakeStarted()
{
print ("Saving all...");
IDE.FileSaveAll();
pass();
}
on debugger:>DebugeeAboutToRun()
{
print ("Saving all...");
IDE.FileSaveAll();
pass();
}
Download SaveOnCompile.zip
- Auto arrange editor windows
- This script arranges editor windows by placing newly opened source or header file to
previously opened header or source with the same name and the corresponding type
(e.g. .h with .cpp, .rh with .rc and .hxx with .cxx).
It is modification done by Chavdar Dimitrov of Kent Reisdorph's example, which can be found at
http://www.reisdorph.com/bcpp/scripts.htm#newedsiz
To use it, myedsize.cpp must be build to a 32-bit multithread DLL, and placed in the BC5\BIN folder.
myedsize.spp
print("myedsize.spp");
import editor;
// import the DLL function
import "myedsize.dll" {
void PositionWindow(char*, int, int, bool);
}
// I like 600 pixels by 350 for my edit windows
declare width = 800;
declare height = 500;
declare ViewID;
on editor:>ViewCreated(newView)
{
ViewID = newView.Identifier;
pass(newView);
}
// if a view was activated and it was not
// an existing window then call the DLL
// function to move it
on editor:>ViewActivated(view)
{
if (ViewID == view.Identifier) {
pass(view);
declare newViewTitle = editor.TopView.Window.Title;
PositionWindow(newViewTitle, width, height, false);
ViewID = NULL;
}
pass(view);
}
///////////////////////////////////////////////////////////////
myedsize.cpp
#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include <cstring.h>
#include <dir.h>
#include <stdio.h>
int xPos;
int yPos;
HWND hWndNew;
HWND hWndExisting;
HWND hWndMDI;
enum FileGroup {
Header,
Source,
Other
};
#define PAIRS_NUM 3
static const char* HeaderSourcePairsExt [][PAIRS_NUM] = {
{".h", ".cpp"},
{".hxx", ".cxx"},
{".rh",".rc"},
};
FileGroup GetFileGroup(const char* pszExt)
{
for (int i = 0; i < PAIRS_NUM; i++)
if (!strcmpi(pszExt, HeaderSourcePairsExt[i][Header]))
return Header;
else
if (!strcmpi(pszExt, HeaderSourcePairsExt[i][Source]))
return Source;
return Other;
}
const char* GetCorrespondingExt(FileGroup fileGroup, const char* pszExt)
{
for (int i = 0; i<PAIRS_NUM; i++)
if (!strcmpi(pszExt,HeaderSourcePairsExt[i][fileGroup]))
return HeaderSourcePairsExt[i][(fileGroup+1)%2];
return 0;
}
int GetOffset()
{
return GetSystemMetrics(SM_CYCAPTION) +(GetSystemMetrics(SM_CYFRAME) * 2);
}
string GetPath(const char* pszWndCaption)
{
string sCaption(pszWndCaption);
int nPos = sCaption.find_last_of(string(":"));
if (nPos != NPOS && nPos != 1)//C:\.....
sCaption.remove(nPos);
nPos = sCaption.find_first_of(string(" "));
if (nPos != NPOS)
sCaption.remove(nPos);
return sCaption;
}
string GetNameExt(const char* pszWndTitle, char* pszName, char* pszExt)
{
string sPath = GetPath(pszWndTitle);
fnsplit(sPath.c_str(),0,0,pszName,pszExt);
return string(pszName) + pszExt;
}
string GetNameExt(const char* pszWndTitle)
{
char pszName[MAXFILE];
char pszExt[MAXEXT];
return GetNameExt(pszWndTitle,pszName,pszExt);
}
BOOL CALLBACK FindExistingWindow(HWND hwnd, LPARAM pszNameExt)
{
const int size = 20;
char className[size];
GetClassName(hwnd, className, size);
if (hwnd == hWndNew || strcmp(className, "BCW5Editor"))
return TRUE;
if (IsIconic(hwnd))
return TRUE;
const int nCurrWndTitleLen = MAXPATH + 3;//title:2
char pszCurrWndTitle[nCurrWndTitleLen];
GetWindowText(hwnd,pszCurrWndTitle,nCurrWndTitleLen);
string sCurrNameExt = GetNameExt(pszCurrWndTitle);
if (sCurrNameExt == (char*)pszNameExt) {
hWndExisting = hwnd;
return FALSE;
}
return TRUE;
}
// callback function called to enumerate
// the child windows
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
const int size = 20;
char className[size];
GetClassName(hwnd, className, size);
if (hwnd == hWndNew || strcmp(className, "BCW5Editor")) return TRUE;
if (IsIconic(hwnd))
return TRUE;
RECT rect;
POINT point;
int offset = GetOffset();
GetWindowRect(hwnd, &rect);
point.x = rect.left;
point.y = rect.top;
ScreenToClient((HWND)lParam, &point);
if (point.y >= yPos)
yPos = point.y + offset;
return TRUE;
}
extern "C"
void PASCAL _export
PositionWindow(char* title, int width, int height, bool bSourceInLeft = true)
{
// reset x and y pos before each run
xPos = yPos = 0;
hWndExisting = 0;
string::set_case_sensitive(0);
// find the IDE window
HWND hWndIDE = FindWindow("CPPFRAME", NULL);
// find the MDI client which is the client
// window of the IDE
hWndMDI = FindWindowEx(hWndIDE, NULL, "MDIClient", NULL);
// get a handle to the newly-created editor
hWndNew = FindWindowEx(hWndMDI, NULL, "BCW5Editor", title);
char pszName[MAXFILE];
char pszExt[MAXEXT];
GetNameExt(title,pszName,pszExt);
FileGroup fileGroup = GetFileGroup(pszExt);
if (fileGroup != Other) {
RECT rect;
if(fileGroup == (bSourceInLeft ? Source : Header)) {
GetClientRect(hWndMDI, &rect);
xPos = rect.right - width;
}
strcpy(pszExt,GetCorrespondingExt(fileGroup,pszExt));
char pszNameExt[MAXFILE + MAXEXT + 1];
sprintf(pszNameExt,"%s%s",pszName,pszExt);
EnumChildWindows(hWndMDI, FindExistingWindow, (LPARAM)pszNameExt);
if (hWndExisting) {
POINT point;
GetWindowRect(hWndExisting, &rect);
point.x = rect.left;
point.y = rect.top;
ScreenToClient(hWndMDI, &point);
yPos = point.y;
}
else
EnumChildWindows(hWndMDI, EnumProc, (LPARAM)hWndMDI);
}
else
EnumChildWindows(hWndMDI, EnumProc, (LPARAM)hWndMDI);
if (hWndNew)
SetWindowPos(hWndNew, 0, xPos, yPos, width, height, SWP_NOZORDER);
}
Download MyEdSize.zip
- Toggle between source and header files
- When editing a source file, this script will bring up the corresponding header file,
and vice versa. Supports these extensions: cpp c h hpp rc rh. Can be extended by editing
a single array ('map'). First searches in the same directory, then does a little heuristics
by replacing parts of the path like '\source\' and '\include\', in order to find files located
in different paths (like Owl files), as suggested by Jogy.
If you too store your headers separately from your source, you can customize another array ('dirMap')
to suit your needs. Currently assigned to <Ctrl-h> (this can be modified)..
import IDE;
import editor;
declare keyCut = "<Ctrl-h>"; // set a keycut you like
declare kbd = IDE.KeyboardManager.GetKeyboard("Editor");
kbd.Assign(keyCut, "CppH_Tog_Launch();");
print("Show Header assigned to " + keyCut);
CppH_Tog_Launch()
{
// just create an object to do the job
new CppH_Tog_Worker();
}
class CppH_Tog_Worker
{
declare topBuf = editor.TopBuffer;
// validate current buffer
if (!topBuf) {
IDE.StatusBar = "CppH_Tog: Invalid top buffer";
return;
}
// You can customize this mapping to better suit your needs.
// It's simply an array of entries, which are themselves
// an array of 2 elements:
// 1. the source extension (of the currently edited file)
// 2. a list (another array) of corresponding extensions, which
// are checked in order of appearance
//
// Note that I've mapped "cpp" first to "h" and then to "hpp".
// That's because I only use .h headers for .cpp files.
// If you're using .hpp headers they will be opened nicely,
// unless you also have a .h with the same name in the directory
// (for interfacing with C programs).
// In that case, just put "hpp" before "h".
//
declare map = {
{ "cpp", {"h", "hpp"} },
{ "h", {"cpp", "c" } },
{ "c", {"h" } },
{ "hpp", {"cpp" } },
{ "rc", {"rh" } },
{ "rh", {"rc" } }
};
// The next array provides mappings for the directory part
// of the filename.
// It's very useful for toggling between Owl source and
// headers, which are in different paths, e.g.
//
// Owl5
// C:\BC5\SOURCE\OWL\window.cpp
// C:\BC5\INCLUDE\OWL\window.h
//
// OwlNext
// C:\Owl\source\owlcore\window.cpp
// C:\Owl\include\owl\window.h
//
// This array contains string pairs. After scanning the directory
// for an open/existing file, we'll start replacing parts of it
// using the 'dirMap' table. The order of the two strings in each pair
// is not significant, since we'll check for both of them and
// replace whichever we find with the other.
// Each modification will be applied to the original path.
// Note that these 'tokens' are delimited by '\' characters
// to avoid partial replacement of directory names.
//
// The predefined pairs are mainly targeted to:
// 1. searching in the same directory;
// a single NULL causes the path to remain unchanged
// 2. Owl5 files.
// 3. OwlNext files.
// 4. Other cases.
// You can add more pairs, and rearrange their order.
//
declare dirMap = {
NULL,
{"\\include\\", "\\source\\"},
{"\\include\\owl\\", "\\source\\owlcore\\"},
{"\\inc\\", "\\src\\"}
};
// get the parts of the buffer's filename
declare drive = topBuf.Drive;
declare path = topBuf.Directory;
declare fname = topBuf.FileName;
declare ext = topBuf.Extension;
// get a list of mapped extensions
declare mapExt = GetMappedExtensions(ext);
// check for unsupported extensions
if (!mapExt) {
IDE.StatusBar = "CppH_Tog: Unsupported extension (" + ext + ")";
return;
}
//======================================
// STEP 1. Check for an existing buffer
//======================================
declare exBuf = GetExistingBuffer();
if (exBuf) {
HandleExistingBuffer(exBuf);
return; // if the above failed, we shouldn't continue
}
//=========================================
// STEP 2. Check if a matching file exists
//=========================================
// iterate through the mapped extensions to check
// if a matching file exists
declare exFile = GetExistingFile();
if (exFile) {
HandleExistingFile(exFile);
return; // if the above failed, we shouldn't continue
}
//======================================================
// STEP 3. Create a new buffer with the first extension
// in the same directory as a last resort.
//======================================================
// the file doesn't really exist, but we open it anyway
HandleExistingFile(drive + path + fname + "." + mapExt[0]);
// THE END
// ----------------------------------
// MEMBER FUNCTIONS FOLLOW:
// ----------------------------------
// ----------------------------------
// Check whether two strings match, ignoring case.
// ----------------------------------
StrIMatch(s1, s2)
{
s1 = (new String(s1)).Upper().Text;
s2 = (new String(s2)).Upper().Text;
return s1 == s2;
}
// ----------------------------------
// Check whether the specified extension
// exists in the mapping array.
// ----------------------------------
GetMappedExtensions(ext)
{
declare ret = NULL;
declare index; // cannot declare this inside 'iterate's parentheses
iterate (declare entry; map; index)
if (StrIMatch("." + entry[0], ext))
return map[index][1];
// we didn't find it
return NULL;
}
// ----------------------------------
// Return the first existing buffer in the IDE that matches
// the mapped extensions, or NULL if non is found.
// ----------------------------------
GetExistingBuffer()
{
declare sentry = 0;
// apply directory mappings
//
iterate (declare tokPair; dirMap)
{
declare xPath = TransformPath(path, tokPair);
if (xPath == NULL) continue; // in case the path didn't change
// walk the buffer list.
//
// explaining the 'for' loop params:
// init: we start checking the next buffer from the top
// cond: a valid buf and not the top buffer (because buffer list is circular)
// CAUTION: don't use "testBuf && (testBuf != topBuf)", it always evals to FALSE (don't know why...)
// step: the next, non-private buffer
//
for (declare testBuf = topBuf.NextBuffer(false);
(testBuf != NULL) && (testBuf != topBuf);
testBuf = testBuf.NextBuffer(false))
{
// iterate through the mapped extensions to check
// if the buffer matches one of them
iterate (declare testExt; mapExt)
{
if (StrIMatch(drive + xPath + fname + "." + testExt,
testBuf.FullName))
return testBuf;
}
// this sentry will terminate the loop
// in case something goes haywire :)
// (perhaps it's not needed...)
if (++sentry >= 1000) break;
}
}
// we couldn't find a valid buffer
return NULL;
}
// ----------------------------------
// If a matching buffer is found, try to open one of its views
// ----------------------------------
HandleExistingBuffer(exBuf)
{
// does it have any views?
if (exBuf.TopView) {
// (is EditView::Window always non-NULL? docs don't mention returning NULL)
exBuf.TopView.Window.IsHidden = false;
exBuf.TopView.Window.Activate();
}
else {
// there are no views attached;
// create a new window; a default view will be created too
declare newWnd = editor.EditWindowCreate(exBuf);
if (newWnd == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit window";
return;
}
}
IDE.StatusBar = "CppH_Tog: OK";
}
// ----------------------------------
// Return the first existing file that matches
// the mapped extensions, or NULL if non is found.
// ----------------------------------
GetExistingFile()
{
// apply directory mappings
//
iterate (declare tokPair; dirMap)
{
declare xPath = TransformPath(path, tokPair);
if (xPath == NULL) continue; // in case the path didn't change
// iterate through the mapped extensions to check
// if the file exists
iterate (declare testExt; mapExt)
{
if (FileExists(drive + xPath + fname + "." + testExt))
return drive + xPath + fname + "." + testExt;
}
}
// we couldn't find an existing file
return NULL;
}
// ----------------------------------
// If a matching file is found, try to create a buffer
// and attach a new view to it.
// (NOTE: Assuming a buffer was not found,
// this function will create a new one)
// ----------------------------------
HandleExistingFile(fname)
{
// create an EditBuffer
declare newBuf = editor.EditBufferCreate(fname);
if (newBuf == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit buffer";
return;
}
// create an EditWindow - a default view will be created too
declare newWnd = editor.EditWindowCreate(newBuf);
if (newWnd == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit window";
return;
}
IDE.StatusBar = "CppH_Tog: OK";
}
// ----------------------------------
// Accepts a string path and a 'dirMap' entry,
// and returns a modified string path.
// By convention, if 'tokPair' is NULL, 'path' is returned
// (to allow searching in the same directory).
// If no replacement was possible, NULL is returned.
// ----------------------------------
TransformPath(path, pair)
{
if (pair == NULL)
return path;
declare n;
declare sPath = (new String(path )).Upper();
declare sTok1 = (new String(pair[0])).Upper();
declare sTok2 = (new String(pair[1])).Upper();
n = sPath.Index(sTok1.Text);
if (n) return StrReplace(path, --n, sTok1.Length, pair[1]);
n = sPath.Index(sTok2.Text);
if (n) return StrReplace(path, --n, sTok2.Length, pair[0]);
return NULL; // could not replace anything
}
// Replaces 'len' characters of string 'src',
// starting at 'pos', with string 'part'.
//
StrReplace(src, pos, len, part)
{
// note that .SubString(n,0) acts like .SubString(n)
// (i.e. it doesn't return "")
//
declare s = new String(src);
return (pos ? s.SubString(0, pos).Text : "")
+ part + s.SubString(pos + len).Text;
}
};
Download CppH_Tog.zip