From d73cc0679907e981b5ca6d1e886b6a81c1bcfb39 Mon Sep 17 00:00:00 2001 From: Robert Dickenson Date: Tue, 7 Jan 2003 17:59:20 +0000 Subject: [PATCH] Temporary fork of candidate base of potententially very useful development tool for ros. svn path=/trunk/; revision=3955 --- rosapps/devutils/vmingw/.cvsignore | 6 + rosapps/devutils/vmingw/CList.cpp | 328 ++++ rosapps/devutils/vmingw/CList.h | 79 + rosapps/devutils/vmingw/GNU-GPL.txt | 340 ++++ rosapps/devutils/vmingw/Makefile.ros | 29 + rosapps/devutils/vmingw/SciLexer.dll | Bin 0 -> 260096 bytes rosapps/devutils/vmingw/SciLexer.h | 300 +++ rosapps/devutils/vmingw/Scintilla.h | 599 ++++++ rosapps/devutils/vmingw/editor.cpp | 834 ++++++++ rosapps/devutils/vmingw/editor.h | 165 ++ rosapps/devutils/vmingw/license.htm | 121 ++ rosapps/devutils/vmingw/license.txt | 59 + rosapps/devutils/vmingw/main.cpp | 2622 ++++++++++++++++++++++++++ rosapps/devutils/vmingw/main.h | 385 ++++ rosapps/devutils/vmingw/process.cpp | 682 +++++++ rosapps/devutils/vmingw/process.h | 146 ++ rosapps/devutils/vmingw/project.cpp | 1453 ++++++++++++++ rosapps/devutils/vmingw/project.h | 295 +++ rosapps/devutils/vmingw/rsrc.h | 168 ++ rosapps/devutils/vmingw/toolbar.bmp | Bin 0 -> 4918 bytes rosapps/devutils/vmingw/treeview.bmp | Bin 0 -> 2870 bytes rosapps/devutils/vmingw/vmingw.prj | 91 + rosapps/devutils/vmingw/vmingw.rc | 399 ++++ rosapps/devutils/vmingw/winui.cpp | 2117 +++++++++++++++++++++ rosapps/devutils/vmingw/winui.h | 529 ++++++ 25 files changed, 11747 insertions(+) create mode 100644 rosapps/devutils/vmingw/.cvsignore create mode 100644 rosapps/devutils/vmingw/CList.cpp create mode 100644 rosapps/devutils/vmingw/CList.h create mode 100644 rosapps/devutils/vmingw/GNU-GPL.txt create mode 100644 rosapps/devutils/vmingw/Makefile.ros create mode 100644 rosapps/devutils/vmingw/SciLexer.dll create mode 100644 rosapps/devutils/vmingw/SciLexer.h create mode 100644 rosapps/devutils/vmingw/Scintilla.h create mode 100644 rosapps/devutils/vmingw/editor.cpp create mode 100644 rosapps/devutils/vmingw/editor.h create mode 100644 rosapps/devutils/vmingw/license.htm create mode 100644 rosapps/devutils/vmingw/license.txt create mode 100644 rosapps/devutils/vmingw/main.cpp create mode 100644 rosapps/devutils/vmingw/main.h create mode 100644 rosapps/devutils/vmingw/process.cpp create mode 100644 rosapps/devutils/vmingw/process.h create mode 100644 rosapps/devutils/vmingw/project.cpp create mode 100644 rosapps/devutils/vmingw/project.h create mode 100644 rosapps/devutils/vmingw/rsrc.h create mode 100644 rosapps/devutils/vmingw/toolbar.bmp create mode 100644 rosapps/devutils/vmingw/treeview.bmp create mode 100644 rosapps/devutils/vmingw/vmingw.prj create mode 100644 rosapps/devutils/vmingw/vmingw.rc create mode 100644 rosapps/devutils/vmingw/winui.cpp create mode 100644 rosapps/devutils/vmingw/winui.h diff --git a/rosapps/devutils/vmingw/.cvsignore b/rosapps/devutils/vmingw/.cvsignore new file mode 100644 index 00000000000..94d6bf97040 --- /dev/null +++ b/rosapps/devutils/vmingw/.cvsignore @@ -0,0 +1,6 @@ +*.o +*.sym +*.coff +*.exe +*.ini +*.bat diff --git a/rosapps/devutils/vmingw/CList.cpp b/rosapps/devutils/vmingw/CList.cpp new file mode 100644 index 00000000000..a9666805be4 --- /dev/null +++ b/rosapps/devutils/vmingw/CList.cpp @@ -0,0 +1,328 @@ +/******************************************************************** +* Class: CList.cpp. This is part of WinUI. +* +* Purpose: A simple way to create doubly linked lists. +* +* Authors: Originally coded by Claude Catonio. +* +* License: Original code was public domain. +* Present revised CList classes are covered by GNU General Public License. +* +* Revisions: +* Manu B. 10/05/01 Terms was translated to English. +* Manu B. 10/16/01 Add CList::Destroy(CNode *node) method. +* Manu B. 11/12/01 Add InsertBefore/InsertAfter methods. +* Manu B. 11/17/01 First() & Last() now returns an integer value. +* Manu B. 11/19/01 CNode::Destroy() returns next node by default. +* Manu B. 12/28/01 Simplify CList, add InsertSorted(). +* Manu B. 03/13/02 Suppress CNode methods, next and prev are public. +* Manu B. 03/28/02 Add Compare(). +* +********************************************************************/ +#include "CList.h" + +/******************************************************************** +* Class: CList. +* +* Purpose: List management. +* +* Revisions: +* +********************************************************************/ +CList::~CList(){ + //MessageBox (0, "CList", "destructor", MB_OK); + while (first != NULL){ + current = first; + first = first->next; + delete current; + } + current = last = first; + count = 0; +} + +/******************************************************************** +* Browse the list. +********************************************************************/ +CNode * CList::First(){ + current = first; +return current; +} + +CNode * CList::Last(){ + current = last; +return current; +} + +CNode * CList::Prev(){ + // Empty list ? + if (first != NULL){ + if(current->prev == NULL){ + // No previous node. + return NULL; + }else{ + // A previous one. + current = current->prev; + return current; + } + } +return NULL; +} + +CNode * CList::Next(){ + // Empty list ? + if (first != NULL){ + if(current->next == NULL){ + // No next node. + return NULL; + }else{ + // A next one. + current = current->next; + return current; + } + } +return NULL; +} + +/******************************************************************** +* Insert nodes. +********************************************************************/ +void CList::InsertFirst(CNode *node){ + if(first == NULL){ + // Empty list. + first = last = node; + }else{ + // Set node pointers. + node->prev = NULL; + node->next = first; + // Insert in the list. + first->prev = node; + first = node; + } + // Set current node, increment the node counter. + current = node; + count++; +} + +void CList::InsertLast(CNode *node){ + if(first == NULL){ + // Empty list. + first = last = node; + }else{ + // Set node pointers. + node->prev = last; + node->next = NULL; + // Insert in the list. + last->next = node; + last = node; + } + // Set current node, increment the node counter. + current = node; + count++; +} + +void CList::InsertBefore(CNode *node){ + if(first == NULL){ + // Empty list. + first = last = node; + }else{ + if (current == first) + first = node; + // Set node pointers. + node->prev = current->prev; + node->next = current; + // Insert in the list. + if (node->prev) + node->prev->next = node; + current->prev = node; + } + // Set current node, increment the node counter. + current = node; + count++; +} + +void CList::InsertAfter(CNode *node){ + if(first == NULL){ + // Empty list. + first = last = node; + }else{ + if (current == last) + last = node; + // Set node pointers. + node->prev = current; + node->next = current->next; + // Insert in the list. + if (node->next) + node->next->prev = node; + current->next = node; + } + // Set current node, increment the node counter. + current = node; + count++; +} + +bool CList::InsertSorted(CNode * newNode){ + // Get the current node. + CNode * currentNode = GetCurrent(); + int cmpResult; + + if(!currentNode){ + // The list is empty, InsertFirst() and return. + InsertFirst(newNode); + return true; + } + + // Compare new node and current node data to know if we must parse Up + // or Down from current node. + cmpResult = Compare(newNode, currentNode); + + // Search Up ----------------------------------------------------------------- + if (cmpResult == -1){ + // Parse the list while there's a previous node. + while (Prev()){ + currentNode = GetCurrent(); + cmpResult = Compare(newNode, currentNode); + + if (cmpResult == 1){ + // Correct position found. + InsertAfter(newNode); + return true; + }else if (cmpResult == 0){ + // Don't add a file twice. + return false; + } + } + // There's no previous node, so insert first. + InsertFirst(newNode); + return true; + } + // Search Down -------------------------------------------------------------- + else if (cmpResult == 1){ + // Parse the list while there's a next node. + while (Next()){ + currentNode = GetCurrent(); + cmpResult = Compare(newNode, currentNode); + + if (cmpResult == -1){ + // Correct position found. + InsertBefore(newNode); + return true; + }else if (cmpResult == 0){ + // Don't add a file twice. + return false; + } + } + // There's no next node, so insert last. + InsertLast(newNode); + return true; + } + // Don't add a file twice (cmpResult == 0) ------------------------------------- +return false; +} + + +int CList::InsertSorted_New(CNode * newNode){ + int cmpResult; + + /* Get the current node */ + CNode * currentNode = GetCurrent(); + if(!currentNode) + return EMPTY_LIST; + + /* Parse up or down ? */ + cmpResult = Compare(newNode, currentNode); + + /* -Up- */ + if (cmpResult == -1){ + // Parse the list while there's a previous node. + while (Prev()){ + currentNode = GetCurrent(); + cmpResult = Compare(newNode, currentNode); + + if (cmpResult == 1){ + // Correct position found. + return INSERT_AFTER; + }else if (cmpResult == 0){ + // Don't add a file twice. + return FILE_FOUND; + } + } + // There's no previous node, so insert first. + return INSERT_FIRST; + + /* -Down- */ + }else if (cmpResult == 1){ + // Parse the list while there's a next node. + while (Next()){ + currentNode = GetCurrent(); + cmpResult = Compare(newNode, currentNode); + + if (cmpResult == -1){ + // Correct position found. + return INSERT_BEFORE; + }else if (cmpResult == 0){ + // Don't add a file twice. + return FILE_FOUND; + } + } + // There's no next node, so insert last. + return INSERT_LAST; + } + // Don't add a file twice (cmpResult == 0) ------------------------------------- +return FILE_FOUND; +} + + +/******************************************************************** +* Destroy nodes. +********************************************************************/ +void CList::DestroyCurrent(){ +// CNode * node = current; + Destroy(current); +} + +void CList::Destroy(CNode * node){ + // Empty list ? + if (current != NULL){ + // Detach node from the list. + if (node->next != NULL) + node->next->prev = node->prev; + if (node->prev != NULL) + node->prev->next = node->next; + + // Set current node. + if(node->next != NULL) + current = node->next; + else + current = node->prev; + + if (current == NULL){ + // Now, the list is empty. + first = last = NULL; + + }else if (first == node){ + // Detached node was first. + first = current; + + }else if (last == node){ + // Detached node was last. + last = current; + } + delete node; + count--; + } +} + +void CList::DestroyList(){ + while (first != NULL){ + current = first; + first = first->next; + delete current; + } + current = last = first; + count = 0; +} + +int CList::Length(){ +return count; +} + diff --git a/rosapps/devutils/vmingw/CList.h b/rosapps/devutils/vmingw/CList.h new file mode 100644 index 00000000000..ac06e127575 --- /dev/null +++ b/rosapps/devutils/vmingw/CList.h @@ -0,0 +1,79 @@ +/******************************************************************** +* Module: CList.h. This is part of WinUI. +* +* License: WinUI is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#ifndef CLIST_H +#define CLIST_H + +#include + +/******************************************************************** +* Generic CNode. +********************************************************************/ +class CNode +{ + public: + CNode() {next = prev = NULL; /*type = 0;*/}; + virtual ~CNode() {}; + + CNode * prev; + CNode * next; + long type; + + protected: + + private: +}; + +/******************************************************************** +* Generic List. +********************************************************************/ +#define FILE_FOUND 0 +#define EMPTY_LIST 1 +#define INSERT_FIRST 2 +#define INSERT_LAST 3 +#define INSERT_BEFORE 4 +#define INSERT_AFTER 5 + +class CList +{ + public: + CList() {first = last = current = NULL; count = 0;}; + virtual ~CList(); + + CNode * GetCurrent() {return current;}; + CNode * First(); + CNode * Last(); + CNode * Prev(); + CNode * Next(); + + void InsertFirst(CNode *node); + void InsertLast(CNode *node); + void InsertBefore(CNode *node); + void InsertAfter(CNode *node); + bool InsertSorted(CNode * newNode); + int InsertSorted_New(CNode * newNode); + + void DestroyCurrent(); + void Destroy(CNode * node); + void DestroyList(); + + int Length(); + + protected: + virtual int Compare(CNode *, CNode *) {return 0;}; + + CNode *first; + CNode *last; + CNode *current; + int count; + + private: +}; + +#endif + diff --git a/rosapps/devutils/vmingw/GNU-GPL.txt b/rosapps/devutils/vmingw/GNU-GPL.txt new file mode 100644 index 00000000000..a3f6b12eec4 --- /dev/null +++ b/rosapps/devutils/vmingw/GNU-GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rosapps/devutils/vmingw/Makefile.ros b/rosapps/devutils/vmingw/Makefile.ros new file mode 100644 index 00000000000..c075b61f3b2 --- /dev/null +++ b/rosapps/devutils/vmingw/Makefile.ros @@ -0,0 +1,29 @@ +# $Id: Makefile.ros,v 1.1 2003/01/07 17:59:20 robd Exp $ +# + +PATH_TO_TOP = ../../../reactos + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = vmingw + +TARGET_CFLAGS = -D_WIN32_IE=0x0400 + +TARGET_SDKLIBS = user32.a comctl32.a ole32.a + +TARGET_OBJECTS = \ + CList.o\ + editor.o\ + main.o\ + process.o\ + project.o\ + rsrc.o\ + winui.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/devutils/vmingw/SciLexer.dll b/rosapps/devutils/vmingw/SciLexer.dll new file mode 100644 index 0000000000000000000000000000000000000000..f1a143b9fbc3cc5da1a408b6954ccff9fdbe0d6d GIT binary patch literal 260096 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%0D)+Ua8g+G;>@Vr;%{u!VI{Q1Yf2A3p4AtS^ICJIs zDa(%zeaHm-O3&Miix2DQg&DK&%0~Yev!_9$M@Z*A9?ZU(0w-xfm!dE zF2arj`vqhzFHzRj_!~~#`s%?4!|kcAxf6!!%I|WWeT>dNR%aisv%jk2M-qiizX1CR zc@4VyBI@iqtMIZ8UQlOm(b+H7rFW6ePOEbC3$U+{cVuqjh@RUnv-nz3UYTiQFVXqy ztU~P*o;$o=u8QZ=gm6*IGw%yqe~Aw`HRKHa=|JRRx{@JCN-yj0|YroFFB=4kQ z_vkRaHtGB)>GG4JvwL;n1C#du;@9tm=VRB(<)W64NoTkGW%ki;m!LiWfw1Fn?6e7i z+kg7S75T3X{WUtyGQ-#`;k?KWK2~SPD`e~!khMGq0vd-lo+ z?$?IaIuL&G;I9nlU+?}n;WEnuH^Ywp#iye;y*5d|0Q;i1qDZkHhu;CrdU>4bp36t z&Ti1zhw1DwI{Q$aoujAXJ6Sg#I8R5=YjyS?>Bi^Bb^YhtI{RBXdy)>H^L6u|;X3=} zI{PI$d%Vs*OlQABXE*5VaXR~XI(v-HK1ydd>g;BneSpqBLT4YSvtOXITXgm-b@stJ z`&Byo5S@Lb&OTIUzffntOlQAHXHV4G2kGpW>g*Tm>m(5PQSL z7Wti$xKhHy-qPAQm$=yEFKYMIlK@#U-$-IvJdg{+W;Z~|hl4a7w5i+pST43gXu~xJ zHaWa6-{_kHzyXN$X*_@&&TJEBw)%1Me2US>(uL%q=68|EODx=upmQfR8~&LAapta| zbNBHz@GIHlckVz8gx!g-2#GVuQ;bM_g;5%YW>Bn8pe$@56bVlKVi@qw0=^7deJM=h z6ZF+&%1@!h?*R_(r!yKbFhPM3ijGb>(L+JU=ciPI1}#o14nB*|&nPyVD8TULS;e+x zDbd2Wg&`dS%F`?24A^Wbh+a)9pu#yt2YYc>10vyIE=nGOzTPK&VpF)8Y(wk5N39Yk)_08OOmOw^hTbPPp*g1!K{O94uu7=3$u46A%;I&!Ci;e}|C`1`C<9A-qQ z1OCV985DN9EwyCr(vnJd8Dy5FhFKY5!WLc!))Q0T0sx|OTXbGdzf;aDc-gs)GqM{3 z&SVnDWdO6HZAw{n+>eYQ9qCcbszm2j*-K_*mStzFxUvO#;i29QO9&X=wOvE|fM-k2)$g!CC!-y&(CVF(SIAWU@H zWP*tO^2Yr2VcML@8=p;zC>oVF?m;_uHs09Gp=x=9UhF;_Z=6u#XnA88BI$VJMie#R zNbkt4}E&*>w!De}6Q`vP*OPuQJck&71A79`~pya7`7;#agkYEV+l@W8%r%y69jQ;VsOy7yW?ETf>Vt~0bi{7Nt-bdKn0Bv zrw$hGBueMHu4Cp-i8LYP=$bGKWrxP)8=ELhOja29b*AGnYi^ zImD9v3#BKhU!tsY9(W(~86Rlk86>?80dP3`lbxW@eM1*5Zcvl`ON5fUZ;`#ZDE)#( zll!0`8+1^c)0vL5O*mV|gqVb?Ora_>A7K=kLymi;ZCLDLMeIILS`QLS@!$yLC&VCt z+^Nj4{(0W((x9YWKiWyJm0JO4JKAMwC6I2E9wpRypUV1cWjGVr65h*W1`yM?g}UHW zhN^p>$n+o^?690nIwK!!>>=ml80OMSKK6p3(o~cz%LfZY`5?pk=cVzvL^u;H!FnUU z1iNDmjl&2&>$yXfCf^ncQQ%`ia3qyzRjH&AUpJYJ)L6dwNR1k5^L~ufoO?v)F29qS zAs;K5pmUFAq*fbr*2yH;fxB%%=cao%fCMFterGLWAnbzU`jJ{`ACXc3KH)+*`|xBv zCo2mDu%L{OJtyj8U^FAOGtjw+qAKVp!L>N4IAEm4#(n4#mENCc6@)A$TKJf77@smy zlf`OFBat0x7ZzzloVcdcEmRQkn{XH?B>fpD)KJ&tK^~1s&pKv0q2!c}ndDIcW1|A; zLZqXDQTxRkkudl|dIzf{(An628w!N#R3TPw#Coa*V!fNl&C8Y;zMMwk&TdG1^fNa1 zv2a0Wx29|ZYDeELIw6ts$ZcLCW}7^2N7%YEM&X+%xAoKq`LBS0|q{0 z>UcFF9$|&a&|~p5g?UE$A8OP0@!(n{)I=G5D8Iu{oIF=ljFfHP7KWc%jAYA~<^pr+ z15k|ms|{TW4dX%A{%9yY{}0gcXOwph4b#u4AJgd6>N#mxUjL8L@LGzeq_5CWi^Mr; zNZF1~!(qT&+761zXD&_B2Q<#d$!_!{gKF0%K%DGL4e0!p`6}9D_{8}HHus^owWWJd zXRHAqIta~R&T6NzTzC$ULe{0OYPVobBBOgL$JnRgD~h3SVVyg~`f1?&VEqhyzjq%Je>@*1ztYGeNe9($+=Reb z#+e}In3Z<%R%P6w$=Am;L6T?hk@?z4pwG+~-EI3W`Fevz|3~vRq9Izo))Q^yeDOIs zawPMtn-vlrfr*-#c?3_N8F%Ix#dAi}^h3&x?O?vc>RH zfp2m`s7-$J>bNp^9{O;fV^_QG+qsc8U;iRhfcvW(H-Msms5;iQq$}lftvxt zA+g+Pfx(;~|Kb!&tno{{9tTY6PIMxczE*qb#k6Iq3;W!+duxUZZoFDgm;%5G0nfAG z2EYn>7*&omod)(MLid8$jQSfeC|v^o|osxH$yOkA{xNf6e!X_`B^ zAIBU>${44%rF?Fs@Tm#8O2qbvNao4B|UG(S_BZ> zOPfleBfqyal>-(Gv%MMQB+x7OJ*DL^N;Q;jvl)O#Np~Qd!2uKkd@OWcjB#-f7H5{o zL3mvEryDW|fhK_T3<;;M=8~65#(d;M@T3F>kbwX;O@jgJt>lg$MmMs?cFls>W@Z~O z1Ky=jEVM#1lH)&;2qV3G9SR0Ki_5HUknzx5rc)N)^Vp;b=oG2kdJ99zEc^ik@;0OM z^bChiwh$#rYj`q!)CU}nfwlEkm zzU>T3Z08`18Q!Cjv7CdokQEN`k1P{0SdI4#kPeV93+{{cPc!)};sw4^lh0)exs38y zPe+TF{M2146qsfd{RB>?fS)L^ol$^ch=!jExL*qVP^N&fvw-FRERPJbh-G00HC1q5 zP5I{tD)~Pn=YLcwe@_TaU*#^TT7`9-oQjo| zW#uJRiBmkwCnerokyzzfg?IZ(5~(3eT7=q30dsg~~6^{o)l zALWPMAlV&(t7&@Kc_EvFuShEGLiVr{6o0KCSOZFXg9ao1#q5EM_hd7;j^Lhh;7Q;j~eJ#D6G&1l~oyD_cEwE8k{DC8dMH{NrwJtl2VtZ~gn zY3A6fp}v~FPIG-|J^Ch7s?om2>}@fJoPFMOd&sk&qQoJJFV}18G>WIJ0ePKNOD{VwD=6Dm~6U_3$VBYX(?c< zDR8`+dN(X2x$P#=)90HxoFs;U!owrny+Moktv5X_7(DQ{_>7IQv7JLuUp~2-%@x%#kGwWTccXZDn+v6%qI^U= zxqO!5KPs7F22L$6B--meF(8L*Fu zAbP5?;;Hy&bLQ8sPg;O&FFBojX)Mz537xTxzJVC$=9mnzYD>n(DhiKbeg;CJ{qiqt z^s^bYSWmCEU}Zzxf-A@v)$YcZXc?^EteQ4)6BX)oljyI59bDvHiw7U+xr#P%3j`OT zQv@mco}=ZszdjzU-@#*b&_N`kZK1LL4G-O2HaB`FeTyeDShesTptyoNJ6O*Qj5?6$ zMTpQCrJhpDNAc65m2^9`(hM|^2~K9+1Ss5@E1m*hj6qkR#Kabw64P8D+0}Rynr@O8 z_`p@tqo}nqJZdTrFr3}9yayN=;_IlQc@MDsds6)e_5c;}k4hGO3=gq>8(bL$x55yt zr_jWXG6l(m61xRO<@49VYj$D2v`!u=`UF%Ev$&m{$)A-)zW5(9YF&i#AzwZD%Ebf} zF}10GhJwpTxySmq6H>k{goL<-@b~!%4{@g1dw>-o`nE4AJvnn|**}CtR-YUc)zjj; z$t?OCC}KUaK&sR1N$@SSbUdx*0S2Md&$76lB|zbjKtzFKB}9(xz6<3&y^L5qRtt$`vxm%E|xueArl3V|7B6bEWjMVrK;THNaQqE`gDXzmJr@fFn-lp42S)bZx!sFTh*DvbdAH^bjg6WTf?k2S9Z^)N^Kn#ZMp-r#_oyIu;fU&aSNa)Z0@Ph|(f4T`|){HF_e0)U>-a8p4 z*C8d;J2;3_%zo!4(OIh?ww(~06p7f^J!eDgFMQvMBi2QT8TEK+(;h{G`1iWjFrkfT|-@t4m&tm9>Lm#?+>{9UOnUpazTNWTd zv>;HMCdD4Z7k9!hwLc$|?{xvzVpeT4we#@FeZX$=>X`raGvh)qINgdhamg$y-o;Kh*CltFgsK*r|@?3 zsm^ieKhK48Igisq?Drm0Bi!GF4ip>)EX6^(!)d{Hm&v#KJMq^D8Qwp@Uw=l^B6DWH z{57-J`+*_#m3t;=c_9SkA}S^4itHZq`uK{#4{b+y#$DTf53V z_uAF1EMj==syw_b7+yZ(?Wl~yyJ*p(uAe;|6^HMg8;6f{IBa7}cvzIACNpwrl8yCc zJZATY$Ea=5Xz?A^@mwrom==3A%dE;eo}BhuXgi|P;L(3H?e}$QpX@j7@AsGX#oPbE ze1D%s4CnhuziGdZ_Z6e&`@w%S?YDGkkI-y8f#%q)rZa8cu2RXx(tfT1YbxFh`U;*h znw#rt!pNVTNrl7itl(s}$R0EtM}jQc8OykfSxkitlZ|sUs5DW6hYzh)=hCIp>s>^P z=NcJ4^o@?s6X(EZIsBvJ(|tC4D8a*r!g9e%rO7frTNys|jgC*oPtQ)D)BWO8%VPFJ zA4>4>p)w79o<^Gp`s`r%&^J0he>ev|_rX6peJndDC;i|<2_8OFt-obTIk^7(Vokj?Z~NJ3BuI z`^6`p#q5WFD8a*rsx<1r8@bDqF56aua z*)l$D@W2sce52!Y!_Uu7pHGl#bbKmV%zp5p1o7~!hCT;BVe~o9@S$&Xd=8ugpEdB0 zj*qbOEc{FfVyILmsQrai#;2X(L*MB5%w$meFRwxHkB(2{+3=wRflqlDpT|CC^pO}o z^o@?s`{%&t;ePQ+eEcl*p#*`?+AuytWqi6BKJ<-_&q@ZhfBIYt|LFADb2fY^LEuvz z#%BW#6r#WAW%$rHIzHc=1D|L6#V7k0XQ2-z2z>Y%dKzzhev;uMd`R_+zR~gVGpPO3 zXDa-o)2Hoh_)vm}4;5yvCj?yLDJyrEt(Om&CUEz&-Ey6Ieiln2xmyPZL(nz~F|- z#xUOAu5^~92}!1T%x;r3OFpZK^#L4|!A=YvuPKloh{IwM?ZTL2C(~guabZ_#w|k&; z1wuEHfY&vc0(P;p?tPF*PwP)~gBSa4MZJ&=*xR`rbn#D)@y&SKDB|Jp5f7y~`>Jie z^>3TRniIZRCb895(|!F^?55s5;`*B~`@Z`^dd=AQkhtJ&lRu#dOE^O3m4Ju2CgQI% zjSY%O=I%>HGX*jFjl=x;2Jw{NJj_4Y0N_;*Kq90NUw;>9-Qh!QoDrVc=ex*XcbKF>*o`2<4)T{Yh06u*KL?Aw#DKov5|I2Js*p$e2Az0PVHSCBL>CRSc89>4EGh9<`Wb#g`uR>-Eou* zSa1q9``uRYkb0IEM;qI*WlZVe)UsWgge)7JC&578Lq^(5mO4k!J|?}>jDy6|rBpGP zKRXuL?sJ}mk2nQ;Vm;!agCE8eN}mj&_3~~w6iV+gb1#>psO)4mC*m=908%8BtC(Gn zS`B0}{WV>Fk0hSLLs=013AEm1OPCQj`B5skd4-a}8{1A3PVcfa)r2{%-k*dc;ye2u_6>orUp(Dkpr9|@QqA_t#bhQ z`_=^1@{vRvx(-t)Ju2e{9MWQ|K1jnW^2R&p=wL&>FR5I zx0?Ot%-1`7MjtlxAwap>D8AMi7n^T}xoWU~ogwvf)%(_fvTG=mlnN1LN^9|S%E$Xs z-`F;KX(BKf4?|#Au&C?B?N2}qF}14V+kMu+Uw`2?UJ@`HP!>Od2l!yD__nX6=Q*rG z3mSiTK=@;C?LC9zK${M_(%-lXcNDmN9@)LUH^$%hAzH7{=z8I)IM>Oi<6Hsg%}{Mn?NHrNjyOissz$W>$fvoPZci;h9Cp)7nc zv9Tf?j2-m&7S(M~xi=qt+>1h?<1<9`LTMATqLqz*>SnWuHW~W{PIF6c%mQo|n7siD z+M|wV00J;o81v*vPE;c3W_4GUtx6fdFG?h%a}JE(ND zu)n64A;b7}F)KDIkkm49%6zO5i&IP;S45;2R0GXKpvm()NXiS(GiCCZ+#k6!Q|u4H z$SlpC6>jNrx+@vP{(RqaBs}D=kF!9P9WM~KpQ0{*a;11wY*D7Gf6D^I@E)|Z7?be!L9gGqC4jml8XxdaF;KNH6g06XN5jtd+Q_gQq$mhI}9u~5wGYLMzQDlXe{59UxV z1j#~=dq!&|mjW(Y$;YUX6mt?p)>SSH2n} zx6c~fu!5~aPsVF4?b$}diylqO$f z&{uFz1>annT5a+q`#_}_>g?ppL1u{>QR=*SHZ(*#AArQ;o!4RPRG8q!4JFU>N+=u& z>ERuf#NwMJk|W5v3+4PA(U*eZcu6jDkT2bg5NtfXq3Z}r72O}aQU3W-7uCo5IS2(z z&=Dk3#a`H6=-WbW1yUWIsbVLgnLq8nbdcN-|AEEur!$hQqWlI=Y%LR=`!F~V*|lOh zK8Cj5K;PJxVu$&wjQ;Hu#dm-u7PO@Pj?PzCWBj-R*O}XA7y4K-`O<~d_A5!Ic2~8F z2Ph;ucj_Y`fV|gVzW@&T;#URIaXh&x2ln~N(cq`Bz}3ex6)X5Fao>oN^i45|_48ri z2~WfmC2MT{1LTBpM+6E#(&ie2FYH?4@(P7qjSkeTIU(XS`yU?z_lU6<+s8&fP1j8O z_Q5xFuzkQmDb^c^zZ#oRS<;By4W-reRj(A^^e524U_mVE_D@CA(9?Mh8XlZh z_6_qHe}a|~&2K2%NQ0)Bpm8e&rB-mnR`1s#_hnR%Ek5%;pYaihw8#0Ku?NLg@$LG+ z`hBbg?-oZ`#IMk4BeALnts(1sX$$+Rhl4L!MB_dbyHPYgk~5V8d`e@dTQFdfTMK0# zDBlxA!E1Sp7>tC_=-oa8f_gXFr-WPR>PpQu=mFtyU zAHnq*TrcOko9m@qU(0nP*Vl8snCUCsrB#cn-JT`mmkLSfla%u5TX99{?q_k9wh14J zW@eaMUA>FNQNmD-$5GaN>EYjfgUcGqJf5`#%>B^sqq{$)4NqL?#H3>VfV3&5^|T** zk=$qFggI(Ez@PZdH=+0!0^xHVXpiVjwvzn*DE=yLozE#aQ1BEwf2Q6mp>|CH6071w zlc^%}9-;QRy*A|AJ!Dzh1Gy7$C~Grfo{{%w_A2mMABd4;EcjnO#{DMxXQdZJ3rw9M zJFTqkCrlwv0z0~=W@j?8qvRFX`D)8qm0)Ex~^d^%wpIUnDX`%$e zWv%tAd$xbSz9%F7RN4(<0D1WnLD5(2X~GhX^v$FQIo-^!PtGn6ai5JssCbu;Qt@W_ zSR2jko$@LHP92-Agd zL`yr<($H9noHR6)Y4XDuU5ru67H5F59u`^lTNpQi|7AYgh+%Rw-v0Y`Sw4}DD#IZy z9#Q8& z(O|?xgn2zOj9jOw3pjaLbN7qab#gz_kNe(!+_&}PUe}L%c|Y!R`f*S1$9;4^?&b)0 zg|6oP?`R0O{{?N{d6;|YfsZ5FU|U!)l~1CU!5!Zr%*^i)W~?R*xG*RXx2WyM3|jjr z_yfitI6(81+q z8kpxwFI@a>D43V9A2ef?v2R6jq5rngh0^vO5a~9P*sYmI5+7t6k1NAY%lm?(LiCpdo@BrhiWL?6natpD5 zx#TMWHZkjDO@RH(=Ow3x%ta1_w%*DlAEJ1G~4IS|d zdPl3Kbk&rtnl`JZt*U98YTCg~EZ-6=`O;P5H%eP|57N_M5ZvF8H*W+{$TwlV$iCM0&5?^ zq9~G)V3A1!tC7K)@6Fi33@P4>T4rDf=59n(vP(Y>10{RuGV-A)(o-N7Pmb)R>&SAsSg9vCNgPYwVf5#BRW{05-f@$?IBoX(!gpzE3BJ!u-+k96h$f~SY*<`+7Sg- zxL9Izu)@VMoM2I84Xo}cu)?(eJ!0^JtVO`mZwN1nA|1iNx`|90SbG?(bMlQ#2Q-Y} z8UWSu%|_xIf+{Vfc^Hmra!~IFZouWt<0!Ahc?uloG^`s6~J;92~eT*I)d_1EFU`}ERjs9L@X>ZSfTXz8DUvl_>*>@4UHZiRV)RB>b2t1I1BSG%G@`=emRs55mKOnY$WidIk(B1a zRcFHWEFj)Ojm?)DxcRgg*|fm?2X|^PO+zl zEfx-%J#t!P#vP#qT)M#{m&&G|vW}pv5qP^84Sox@?vDm7ube@HroPp2F4iM7hVa|{ z-eA{`VMAPtM-Fjq9XrI;eB%&TasCk3@TJh78{%@jG{m*PZHQ~{r$bzoy+d5x7h})Q z8s~CPk8=$#jB}OWhNcrgg4F~#tb_Y+{wclA12y7$lWQ~7Zm0lM?l_aH7-~J# zW~cy^mK-NxH{O7FP!6a$P>Z4Zpk|CWx#mN4LG?lzZ#22aKuv>M47C<&C)5$BlTcc? zdb0rznN~fofspkZc$jbDPG+)(xS7ISi!kGP7=fF~YT#xHW8`LR zoCpKBnU)0Sax-?dgn2OE$l=6rGg)J~ncxiMW`Z+_n+eW*ZYDV2hdGJExs031I)a-C zj+vVY&Ur9fdH5mROx8GVrts%;Glh?b*~Y_LxS6a&VYYMkVcbmC3t)C|_d3vx%w*lb z%>+M@havb2U{2=Y6S$eIUW6xi3V$!mkblH}7a|O->~|42Q+UNp;YV?IqE#&dQ+P`2 zR=DF?Oa_zOzt7F@0r-4wCOmVvnbMuh&4kZnZhjx(0gC-DhJnn4!*CdIev17rfq4SQ ze4bR(bTVJT&4lNbFwf!cSHWDw&7--Q!dwmWKl?MNKMqN?pJAW? z2H^~6)j@+wDE8Y>=sqZ=$TWV~>?Y)OzY(v>ZKlpyD6ffg?M8P;@+c=xYOfv4(ow>f{>NZfBa~uS^xUCn$M%|Bmfx9NOs?h}v~5?z{Th>NFI4MTlWYHIv|VtU57juw z@>NWTG74%rn$i6a$gB|s06^84_z7#cf?-{rQk;Twkgr^Q|P1MmtSRy zpqYXng)=@G>1TObwiABye;bM4xMMPY3VcO37lmPH@f*_=S>6<0>%VtKB+VTs2D?h3 z%utT^2fOA&xuF`N_CRg=(_ohb-So%7u7rJYuHNV3T;pKwh1mg>4|6S4Il`TQ(xye` z83Ts60#J^Dk^S|2@C5NiE0i{ls|z&K-p9IN2BlFU&=J;kG{h}XQJ<(11Nh^ zD1V~wj(5YfROq|sKO@Us!O?v`==DG(&g7T<;9%E&C?%YtCmx8TzXCrO?uz-J(Uo)* zef`KV4*Q$sv`PLQ`ESA~TnR_I>1EkYq9Vzz_n*W4lem8XBEcw}@}rB*WS++T6?eK| zOy0W({*Elvx~cL)1{vsl>Gy`c$>KUaqgZV%HaqW{rb3nw=N!C z115iyuFN)bcap_O{(3sKbAJ+!PW}xT36rk;#$k3q=Dq#Ir@QjxKjsIK@pg8H8+4<= zC@lVKtT68Lu-j<3NpPE{aoYnoV^6Hmrg3YA+a|c3(6~*DF$!DZw&05}yi&Lg|68oE zR^tXSHi83g{r!fYiWNpfWkbz}s)VYA+6uK3stKwY>KIfzR5z4xI##eijfP5xngdl1 zRR^^dYBy99R5Mf?)Jdprs6HrjZ>%r^Y8+HLl=7Pab1BqXs7+A2pp;)T%*UWkLUltK zzl;?UphiPEpr%1BhH^tSKy8KE1=R%A3UwSxg6f5`e1&*W4ybIX`B0TmwNQ;vTcLJB z?S*QFIsv8pdNgL?YvcuLIMisUB&c+#T&NjPbD$POl|!wCs)K5T+6J`?YA;j(>Il?v zsCK9>s9q>zAMk`40W}870hJ9k14{YLhq)ALEz~Bc9Z{zvK?R`Npd_dsDC4)tC)8*t2h=pE`B3FhwNQ;vJE5AP+MwE@ zx}k&+$_Xk7DirxE~_e8>YfaD2Y1hRm6y2PB|@@lhplSWlqyekDaD_lxRQH3yv$&FwDRLLrQ^XabEWZ{*l?(>9KBi&hOyKS;? zB&z#7;dRA*W{JD1Y-u&o>0Mb`T{SY4gS-?_#@-iZl&vb6Qvq+GU6@(18fNEOLHL`H zUs1kpIo<&ggs+5x5?6WIoh1r^;r0#OmbzW5mY0_ZMnge`XH_wSXEqdqhD+TF-Ol57 zCF(HP-BWH?$bfYR*oh94%gdG{F}q^tAubZ8uUrXI5ua34m(j~4g~-sV5RjW)D`nVY!tT>ttBP5Q+2odARk3t( zaWVL;nsB^>+~$-m1+^iIP!R4U``nVMY7o(hO#Q$xwY*}9t9&whuLx&wxt%bj_z!UV zjEbc!&s(^?5UfD{Te-bx72Z2Sh~F8QG(@tL6i;8Zw5nt!SX&TYG)%9~osv^Hqr_D_ zWu3c(_^Z`0qrz3p>4DsSWSHqG&n;U`a6cxqyNrU)shC$*T#{4jqB?WhfC^XXLDfP@ z$Xvkalo-PcofVcKl*XXIHMI4|6qc8iR0NvLl*eKNvI5 zRp!pCs44`nm6s^&EW8|}AT*~!#S-yLg+*(s%Fy`WH&$4*sI1ymy|k=MxQ>~ZRurKggB!7ZP= z$&CxuJVCe%?a4CPfz?`y>xCOgP_d53t5fW}ReD@-uB>#gi%9P`f^$_d$MOZVIpyW7 z85WLF`!A!+9Ny-38Pi;s8_aWpxp}HksQDFWG2SOTI=>H?UcNjBY&AU>^^w^tJm{nW zap~=IAl8)d{e;}}DwcW>_cJozRI;wnjZPhY-Q3OyGsCs6!s8a=SR3W4qDEmTnL)~m z@^WhLgbTv<0`w{j{zc4fUA59#T*B?{l9jwy!}>hA$@G~~v1&PyRu~(0V|mX&yR;fC zQVi5&>OgKQ+9Z{bsOAvRI(fCLtlWi65{!9b6~C9|$f{t|X$Fg^?0S?^DI`pQsPTCqmS5vEaw!gZ**EAw4d z==xBFtL3h7NX(on*V5bbHC0TwB&Mj6%2$m|YY_iNH8pp--8R0soZ96C;GtL3XU>Fw z?hIP%9|Qk?r@F~maI^3wj%I`v9fPj1niBQ>4 zat@dQpEG}atLjV-tqT!}6mE_(Md`(w0DLPHs9@;D1}xMds8}en3#8UUr9cgbLim1u zv|rZm4|m@}A8>_xWub1I%IvL%S{e%V#mXuGy&b9>s+YTc3q3^23v~$ULns1v=8twZ z4WL*yqn5lAY>RaO+qpC*#@8tnz%(5rsheS+j&B~!^gCeu>|10Q`?gd_gH=6?`O+B9 z$b7h!X&AoXH&<{8Re)0_lnW(*xk^|juqiKFXQQ3fDuh@iRKp*4ED^2(Hu?=V?lF=? zQ#>jI_bT|T5|&4Sw2FmE!k92gNQH7>l^_YRmIzk>ryRgr30|c%)*(kO*jP6Ya|y#L z5i5NaLNQ=hv$PWtQuZkYt*V8kEM>y1oZ&bgp{fv?es^PLVNh|(MLY^mxK>8wr7#MV zT$V@@QTkF;iS*pzR=PvIQ0$t8Ctp5qahXsP5eA26syJ)osq zlSASpeQDzS2%}+S96cqqbR=5-Kl?)ie-g+&mo(T~V12^2*Vbg)ZwuI(ZLPK=wl>=_ z+i}|oTf6O~O|o^_x@|qSUR$3{up8|ryV-8BC)kJEN7xhXqwQnta`jGW$>tg#gj-4qF zOnP)ucIK^F!eaT{%6!`b+hSX>t<+X-tF*aoYi;XowYEB2gKd+o(YD#P)wa#H!?x45 z%eLFLCkkhD+YEN<)Ts;Hoz|5mG|J`^M1vi&xytqfhp-1XqTuv-MsG%6hLCB@G-aAI zEtv_K!!t)@CT5P#9FsXNGbz)NnUa~FnVp%NIW2QWW`5?J%=wuMG8bnSXO?D`XI5sq zGuLLW&#cX?%WTNpl-ZcMIdf~~w#*%wJ2Q7>?#|qkxi_;ZbAM(avpKUh^GIe}=CRD< znI|&aGf!qpnO&LPnLU}knSGf;mNCneWzMo>C1efH8j+QlH9Bid*0`*sEJs#KR(e); zR&Lg`tQlGPS#z@HXD!HDoK>7vnpK`vndQz}nMXeb4%Vb-Hc2?avdve3q0Hl;PDZBE;owk>T(+Rn6HX}i<*r0q>>O52|nNNY}OO*@j-mUb-dcv@Blu~D`Yoc|ub&PeKHOcC*rdZRh+16a^H0um&zIBduzIB0hv9;J* zYAv@`THV&Q*7ep}Yn`>hy2;vT-E7@z-Dcfk-D%xr-L0ej5o??EnDw~zgtgsz(kfZI ztXJ8V+78)nx8Gxb(EdyN^Y)J%U5;)?kE7So=Ma*O$);p;vL!hoc}?=?$rntRKH;8; zm!({hGCswbBDB${OArpF9!ouu+L8K2YV4#NCOwFf`Dxna=}%+|?Xv%M6ShyZrnpml zDX*v8o@$=-mq{zrmS?_@DRj%cb1-QcaA~pS+5eRKS?X`nE=>nejOoVVYq0$qt?O*Z zF2~ywPfZ*Q-ncQPA?1QeBPLxl>BaO9(i=10z$3{q7z5zkT~cjQL(-3uwkB-=C4LQ_ zd%@abHQTPWjkBfMHh|ZrX3WSa%veJ8J~0M;t03e}`2K|Q3HMKUYC_9|_b2pB7&P(H zi8oBlM!UIeqIcp$6Yoi_OZBDdx$HMtd$OL*5|UzAy}H3#>%ihD!}nK?CP$0oZO5$S zMae6ZYm!|PD<|GP@rU5*i&L&nNltkv<98WCehj1A)k)VS-Iz2XDKF`!r2M3LNvG3~ zW?V?PEskOJrYkAddXaT3%6^u0iPd9$5T*H&^?WH=ZrvubThv^6% zqZT?rC+Re`(|PKk%hX9-bdzpT5B1VL>Z5=PR}m^wMX6{N1LfjXqDoRJiYZem<*HPb zrqb0km4RxXrE*oC%2$ikGF1St6sZzbs>-1C7FDU{dyBng_(UtcBCo_N^~%1cy8ioQ zhfbx?AN%|D)^Cr|Yuq#Xi~tYk5j>Jd@n{~y<9IwzQ3Fcm$crCbN9Dn$@wRNX^gLW5!cPlt>f@WTQMRkH}-P zMGm$j?Z@mfcCu~Q6YX^S1$(}|$bQ-WpCmR{B!;#|C-sXzjlQq}2o}j1bOr4`& z(o6LUU930g3cX!d>ssBQn{=~o)ouEmzND||ZhcqZ2TS3;4Bk781=(;G%My@1oY`yw zo5C_#4tt3$Wh+=Q+rTQ2pw&>Ofi!0Id+L%19RSG_gR<`G=>|oMuL%SaKknx z7*oLGImoA_#tNg@*kDu`+l^|Y7Wvy`G$XIturrs8Yeu(m*SK$l@gN@#KP2#E&biGe za4f0-cdzi6Czr?-a*eE%HFBSPPo9=t^0stn3B8K!IfkT(Qihs}oY<^(s8LpdHQ1hG zZ?gwGvz?zf-*H#FZ@TH;0_4L+^!pm`E$=NqP>Opv_}k;y0%l;Xi;PuR)hEUmMvx2c zff|Q~#zMEuPzA`oHFOcw9&XMsmztZ*o#uz=g^!3)VCr;nPdpGLe~xusk$;eJ#OVhh z>v!mVq+Jk6Hdn1xTh)8^3(h=et+Nq5@E6WOrwL4Q(mCsV;@of^I3wM7H_=UTnJe69 z-RIqGcaB@)mbx3=o$mYYpWG2%p*I?Yo~Z+s1M9wOMvCd8Q0x;o#4+s1Fd9wIQ8ulm zt@La99X+SA)q1rJKKon^w-QiwOE5XqSf5(At&#Rq_EGzk9dKeD%b5&z+T*TB z(qz!*6cFc1y&kUH3&)*@+j@0iFSJA^hO=RC7=yd=;jA)N#a@S-THvH!xF{NI^H7Zp zxTXw_sY9u%TlPCYEAMDRttIXcO(CTZGG? zOq8a4M&`&oSuCq$HL~S|JS)3pj|`$`CZkVg(R><*u9d1LtM5VUSJaPHpBwaIyh&cB z*XCXKzACYo=u%y#%k>srsjKuZy&Jn)r|b0ru*PA1L>~iF;(iyroPbRC_#|ZcEZ&Uy z_X3EZ3p208G&>`d9aQIWXXp|&ITxKT!D!>X7rkO{ zkJk!re&CJt$N4k;eZHZm>N$F=-jDTO(cs{g0Y5~8aNb3R3<23rHWq?dtHC69j3>Co zC-Oqf*l&kE3SGs-9Bu9~Pnc)S4)asO(S$kkw74KT#b@FRabNsJ43RN%v`mo(w4EfU%9%1>zATI6TDetjmp_%S zql+Ac(x>Fd*pKVTnm+kWilPxT2AYp23v@ICTr{5wu@h@(BRHrA`*5hg>OTPYbkb+k zjrtE)LqRxCsP8JSNIe6hnGKd%qE@SQ>PJY0-D;m|RBx-_sy6izYW1eNqx#e!Ynb)8 zHOd-;o@rapT6yRag;s-g&~CNc?elhrecA4`yX>3xExX6=weQ(|sO4}c!ijXEoH!@Y zj{AuHwHCo5Srm(AF)WV7vqYA}Qc!!TERChJY1sKJHjCx5Jk;W1wu}|9m8^)BfR@X^ z%V~d`_{%WkZ!s&)Dsvb1|D<^uG}-wt=71OxC*q+-l1LFunE!O<@bAtC{?p08X;k8Q z(IGBFy)JQ6+!8&a7m3>^0y11i$VeF_qoHP;jPI}2G?@i07lYgjhNESFo* zJF4U^xm)g)b+TSQ_j)|mG_`=fWj$)BB69N#ZcV;%*9op;RB%H6aO{$ zn#hfGxFQdHTL7*t2h;9V_3DUfQSGV&e&|sFE5eGh;;kf0S*bYxnFT)-SVdO3RcYa9lWh;`Cxw>qqwR?on}C$ixG +// The License.txt file describes the conditions under which this software may be distributed. + +// Most of this file is automatically generated from the Scintilla.iface interface definition +// file which contains any comments about the definitions. HFacer.py does the generation. + +#ifndef SCILEXER_H +#define SCILEXER_H + +// SciLexer features - not in standard Scintilla + +//++Autogenerated -- start of section automatically generated from Scintilla.iface +#define SCLEX_CONTAINER 0 +#define SCLEX_NULL 1 +#define SCLEX_PYTHON 2 +#define SCLEX_CPP 3 +#define SCLEX_HTML 4 +#define SCLEX_XML 5 +#define SCLEX_PERL 6 +#define SCLEX_SQL 7 +#define SCLEX_VB 8 +#define SCLEX_PROPERTIES 9 +#define SCLEX_ERRORLIST 10 +#define SCLEX_MAKEFILE 11 +#define SCLEX_BATCH 12 +#define SCLEX_XCODE 13 +#define SCLEX_LATEX 14 +#define SCLEX_LUA 15 +#define SCLEX_DIFF 16 +#define SCLEX_CONF 17 +#define SCLEX_PASCAL 18 +#define SCLEX_AVE 19 +#define SCLEX_ADA 20 +#define SCLEX_LISP 21 +#define SCLEX_RUBY 22 +#define SCLEX_EIFFEL 23 +#define SCLEX_EIFFELKW 24 +#define SCLEX_TCL 25 +#define SCLEX_AUTOMATIC 1000 +#define SCE_P_DEFAULT 0 +#define SCE_P_COMMENTLINE 1 +#define SCE_P_NUMBER 2 +#define SCE_P_STRING 3 +#define SCE_P_CHARACTER 4 +#define SCE_P_WORD 5 +#define SCE_P_TRIPLE 6 +#define SCE_P_TRIPLEDOUBLE 7 +#define SCE_P_CLASSNAME 8 +#define SCE_P_DEFNAME 9 +#define SCE_P_OPERATOR 10 +#define SCE_P_IDENTIFIER 11 +#define SCE_P_COMMENTBLOCK 12 +#define SCE_P_STRINGEOL 13 +#define SCE_C_DEFAULT 0 +#define SCE_C_COMMENT 1 +#define SCE_C_COMMENTLINE 2 +#define SCE_C_COMMENTDOC 3 +#define SCE_C_NUMBER 4 +#define SCE_C_WORD 5 +#define SCE_C_STRING 6 +#define SCE_C_CHARACTER 7 +#define SCE_C_UUID 8 +#define SCE_C_PREPROCESSOR 9 +#define SCE_C_OPERATOR 10 +#define SCE_C_IDENTIFIER 11 +#define SCE_C_STRINGEOL 12 +#define SCE_C_VERBATIM 13 +#define SCE_C_REGEX 14 +#define SCE_C_COMMENTLINEDOC 15 +#define SCE_C_WORD2 16 +#define SCE_H_DEFAULT 0 +#define SCE_H_TAG 1 +#define SCE_H_TAGUNKNOWN 2 +#define SCE_H_ATTRIBUTE 3 +#define SCE_H_ATTRIBUTEUNKNOWN 4 +#define SCE_H_NUMBER 5 +#define SCE_H_DOUBLESTRING 6 +#define SCE_H_SINGLESTRING 7 +#define SCE_H_OTHER 8 +#define SCE_H_COMMENT 9 +#define SCE_H_ENTITY 10 +#define SCE_H_TAGEND 11 +#define SCE_H_XMLSTART 12 +#define SCE_H_XMLEND 13 +#define SCE_H_SCRIPT 14 +#define SCE_H_ASP 15 +#define SCE_H_ASPAT 16 +#define SCE_H_CDATA 17 +#define SCE_H_QUESTION 18 +#define SCE_H_VALUE 19 +#define SCE_H_XCCOMMENT 20 +#define SCE_H_SGML 21 +#define SCE_HJ_START 40 +#define SCE_HJ_DEFAULT 41 +#define SCE_HJ_COMMENT 42 +#define SCE_HJ_COMMENTLINE 43 +#define SCE_HJ_COMMENTDOC 44 +#define SCE_HJ_NUMBER 45 +#define SCE_HJ_WORD 46 +#define SCE_HJ_KEYWORD 47 +#define SCE_HJ_DOUBLESTRING 48 +#define SCE_HJ_SINGLESTRING 49 +#define SCE_HJ_SYMBOLS 50 +#define SCE_HJ_STRINGEOL 51 +#define SCE_HJ_REGEX 52 +#define SCE_HJA_START 55 +#define SCE_HJA_DEFAULT 56 +#define SCE_HJA_COMMENT 57 +#define SCE_HJA_COMMENTLINE 58 +#define SCE_HJA_COMMENTDOC 59 +#define SCE_HJA_NUMBER 60 +#define SCE_HJA_WORD 61 +#define SCE_HJA_KEYWORD 62 +#define SCE_HJA_DOUBLESTRING 63 +#define SCE_HJA_SINGLESTRING 64 +#define SCE_HJA_SYMBOLS 65 +#define SCE_HJA_STRINGEOL 66 +#define SCE_HJA_REGEX 67 +#define SCE_HB_START 70 +#define SCE_HB_DEFAULT 71 +#define SCE_HB_COMMENTLINE 72 +#define SCE_HB_NUMBER 73 +#define SCE_HB_WORD 74 +#define SCE_HB_STRING 75 +#define SCE_HB_IDENTIFIER 76 +#define SCE_HB_STRINGEOL 77 +#define SCE_HBA_START 80 +#define SCE_HBA_DEFAULT 81 +#define SCE_HBA_COMMENTLINE 82 +#define SCE_HBA_NUMBER 83 +#define SCE_HBA_WORD 84 +#define SCE_HBA_STRING 85 +#define SCE_HBA_IDENTIFIER 86 +#define SCE_HBA_STRINGEOL 87 +#define SCE_HP_START 90 +#define SCE_HP_DEFAULT 91 +#define SCE_HP_COMMENTLINE 92 +#define SCE_HP_NUMBER 93 +#define SCE_HP_STRING 94 +#define SCE_HP_CHARACTER 95 +#define SCE_HP_WORD 96 +#define SCE_HP_TRIPLE 97 +#define SCE_HP_TRIPLEDOUBLE 98 +#define SCE_HP_CLASSNAME 99 +#define SCE_HP_DEFNAME 100 +#define SCE_HP_OPERATOR 101 +#define SCE_HP_IDENTIFIER 102 +#define SCE_HPA_START 105 +#define SCE_HPA_DEFAULT 106 +#define SCE_HPA_COMMENTLINE 107 +#define SCE_HPA_NUMBER 108 +#define SCE_HPA_STRING 109 +#define SCE_HPA_CHARACTER 110 +#define SCE_HPA_WORD 111 +#define SCE_HPA_TRIPLE 112 +#define SCE_HPA_TRIPLEDOUBLE 113 +#define SCE_HPA_CLASSNAME 114 +#define SCE_HPA_DEFNAME 115 +#define SCE_HPA_OPERATOR 116 +#define SCE_HPA_IDENTIFIER 117 +#define SCE_HPHP_DEFAULT 118 +#define SCE_HPHP_HSTRING 119 +#define SCE_HPHP_SIMPLESTRING 120 +#define SCE_HPHP_WORD 121 +#define SCE_HPHP_NUMBER 122 +#define SCE_HPHP_VARIABLE 123 +#define SCE_HPHP_COMMENT 124 +#define SCE_HPHP_COMMENTLINE 125 +#define SCE_HPHP_HSTRING_VARIABLE 126 +#define SCE_HPHP_OPERATOR 127 +#define SCE_PL_DEFAULT 0 +#define SCE_PL_ERROR 1 +#define SCE_PL_COMMENTLINE 2 +#define SCE_PL_POD 3 +#define SCE_PL_NUMBER 4 +#define SCE_PL_WORD 5 +#define SCE_PL_STRING 6 +#define SCE_PL_CHARACTER 7 +#define SCE_PL_PUNCTUATION 8 +#define SCE_PL_PREPROCESSOR 9 +#define SCE_PL_OPERATOR 10 +#define SCE_PL_IDENTIFIER 11 +#define SCE_PL_SCALAR 12 +#define SCE_PL_ARRAY 13 +#define SCE_PL_HASH 14 +#define SCE_PL_SYMBOLTABLE 15 +#define SCE_PL_REGEX 17 +#define SCE_PL_REGSUBST 18 +#define SCE_PL_LONGQUOTE 19 +#define SCE_PL_BACKTICKS 20 +#define SCE_PL_DATASECTION 21 +#define SCE_PL_HERE_DELIM 22 +#define SCE_PL_HERE_Q 23 +#define SCE_PL_HERE_QQ 24 +#define SCE_PL_HERE_QX 25 +#define SCE_PL_STRING_Q 26 +#define SCE_PL_STRING_QQ 27 +#define SCE_PL_STRING_QX 28 +#define SCE_PL_STRING_QR 29 +#define SCE_PL_STRING_QW 30 +#define SCE_L_DEFAULT 0 +#define SCE_L_COMMAND 1 +#define SCE_L_TAG 2 +#define SCE_L_MATH 3 +#define SCE_L_COMMENT 4 +#define SCE_LUA_DEFAULT 0 +#define SCE_LUA_COMMENT 1 +#define SCE_LUA_COMMENTLINE 2 +#define SCE_LUA_COMMENTDOC 3 +#define SCE_LUA_NUMBER 4 +#define SCE_LUA_WORD 5 +#define SCE_LUA_STRING 6 +#define SCE_LUA_CHARACTER 7 +#define SCE_LUA_LITERALSTRING 8 +#define SCE_LUA_PREPROCESSOR 9 +#define SCE_LUA_OPERATOR 10 +#define SCE_LUA_IDENTIFIER 11 +#define SCE_LUA_STRINGEOL 12 +#define SCE_ERR_DEFAULT 0 +#define SCE_ERR_PYTHON 1 +#define SCE_ERR_GCC 2 +#define SCE_ERR_MS 3 +#define SCE_ERR_CMD 4 +#define SCE_ERR_BORLAND 5 +#define SCE_ERR_PERL 6 +#define SCE_ERR_NET 7 +#define SCE_ERR_LUA 8 +#define SCE_ERR_DIFF_CHANGED 10 +#define SCE_ERR_DIFF_ADDITION 11 +#define SCE_ERR_DIFF_DELETION 12 +#define SCE_ERR_DIFF_MESSAGE 13 +#define SCE_BAT_DEFAULT 0 +#define SCE_BAT_COMMENT 1 +#define SCE_BAT_WORD 2 +#define SCE_BAT_LABEL 3 +#define SCE_BAT_HIDE 4 +#define SCE_BAT_COMMAND 5 +#define SCE_BAT_IDENTIFIER 6 +#define SCE_BAT_OPERATOR 7 +#define SCE_MAKE_DEFAULT 0 +#define SCE_MAKE_COMMENT 1 +#define SCE_MAKE_PREPROCESSOR 2 +#define SCE_MAKE_IDENTIFIER 3 +#define SCE_MAKE_OPERATOR 4 +#define SCE_MAKE_TARGET 5 +#define SCE_MAKE_IDEOL 9 +#define SCE_CONF_DEFAULT 0 +#define SCE_CONF_COMMENT 1 +#define SCE_CONF_NUMBER 2 +#define SCE_CONF_IDENTIFIER 3 +#define SCE_CONF_EXTENSION 4 +#define SCE_CONF_PARAMETER 5 +#define SCE_CONF_STRING 6 +#define SCE_CONF_OPERATOR 7 +#define SCE_CONF_IP 8 +#define SCE_CONF_DIRECTIVE 9 +#define SCE_AVE_DEFAULT 0 +#define SCE_AVE_COMMENT 1 +#define SCE_AVE_NUMBER 2 +#define SCE_AVE_WORD 3 +#define SCE_AVE_KEYWORD 4 +#define SCE_AVE_STATEMENT 5 +#define SCE_AVE_STRING 6 +#define SCE_AVE_ENUM 7 +#define SCE_AVE_STRINGEOL 8 +#define SCE_AVE_IDENTIFIER 9 +#define SCE_AVE_OPERATOR 10 +#define SCE_ADA_DEFAULT 0 +#define SCE_ADA_COMMENT 1 +#define SCE_ADA_NUMBER 2 +#define SCE_ADA_WORD 3 +#define SCE_ADA_STRING 4 +#define SCE_ADA_CHARACTER 5 +#define SCE_ADA_OPERATOR 6 +#define SCE_ADA_IDENTIFIER 7 +#define SCE_ADA_STRINGEOL 8 +#define SCE_LISP_DEFAULT 0 +#define SCE_LISP_COMMENT 1 +#define SCE_LISP_NUMBER 2 +#define SCE_LISP_KEYWORD 3 +#define SCE_LISP_STRING 6 +#define SCE_LISP_STRINGEOL 8 +#define SCE_LISP_IDENTIFIER 9 +#define SCE_LISP_OPERATOR 10 +#define SCE_EIFFEL_DEFAULT 0 +#define SCE_EIFFEL_COMMENTLINE 1 +#define SCE_EIFFEL_NUMBER 2 +#define SCE_EIFFEL_WORD 3 +#define SCE_EIFFEL_STRING 4 +#define SCE_EIFFEL_CHARACTER 5 +#define SCE_EIFFEL_OPERATOR 6 +#define SCE_EIFFEL_IDENTIFIER 7 +#define SCE_EIFFEL_STRINGEOL 8 +//--Autogenerated -- end of section automatically generated from Scintilla.iface + +#endif diff --git a/rosapps/devutils/vmingw/Scintilla.h b/rosapps/devutils/vmingw/Scintilla.h new file mode 100644 index 00000000000..0185d3e5be6 --- /dev/null +++ b/rosapps/devutils/vmingw/Scintilla.h @@ -0,0 +1,599 @@ +// Scintilla source code edit control +/** @file Scintilla.h + ** Interface to the edit control. + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +// Most of this file is automatically generated from the Scintilla.iface interface definition +// file which contains any comments about the definitions. HFacer.py does the generation. + +#ifndef SCINTILLA_H +#define SCINTILLA_H + +// Compile-time configuration options +#define MACRO_SUPPORT 1 // Comment out to remove macro hooks + +#if PLAT_WIN +#ifdef STATIC_BUILD +void Scintilla_RegisterClasses(HINSTANCE hInstance); +#endif +#endif + +// Here should be placed typedefs for uptr_t, an unsigned integer type large enough to +// hold a pointer and sptr_t, a signed integer large enough to hold a pointer. +// May need to be changed for 64 bit platforms. +typedef unsigned long uptr_t; +typedef long sptr_t; + +typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam); + +//++Autogenerated -- start of section automatically generated from Scintilla.iface +#define INVALID_POSITION -1 +#define SCI_START 2000 +#define SCI_OPTIONAL_START 3000 +#define SCI_LEXER_START 4000 +#define SCI_ADDTEXT 2001 +#define SCI_ADDSTYLEDTEXT 2002 +#define SCI_INSERTTEXT 2003 +#define SCI_CLEARALL 2004 +#define SCI_CLEARDOCUMENTSTYLE 2005 +#define SCI_GETLENGTH 2006 +#define SCI_GETCHARAT 2007 +#define SCI_GETCURRENTPOS 2008 +#define SCI_GETANCHOR 2009 +#define SCI_GETSTYLEAT 2010 +#define SCI_REDO 2011 +#define SCI_SETUNDOCOLLECTION 2012 +#define SCI_SELECTALL 2013 +#define SCI_SETSAVEPOINT 2014 +#define SCI_GETSTYLEDTEXT 2015 +#define SCI_CANREDO 2016 +#define SCI_MARKERLINEFROMHANDLE 2017 +#define SCI_MARKERDELETEHANDLE 2018 +#define SCI_GETUNDOCOLLECTION 2019 +#define SCWS_INVISIBLE 0 +#define SCWS_VISIBLEALWAYS 1 +#define SCWS_VISIBLEAFTERINDENT 2 +#define SCI_GETVIEWWS 2020 +#define SCI_SETVIEWWS 2021 +#define SCI_POSITIONFROMPOINT 2022 +#define SCI_POSITIONFROMPOINTCLOSE 2023 +#define SCI_GOTOLINE 2024 +#define SCI_GOTOPOS 2025 +#define SCI_SETANCHOR 2026 +#define SCI_GETCURLINE 2027 +#define SCI_GETENDSTYLED 2028 +#define SC_EOL_CRLF 0 +#define SC_EOL_CR 1 +#define SC_EOL_LF 2 +#define SCI_CONVERTEOLS 2029 +#define SCI_GETEOLMODE 2030 +#define SCI_SETEOLMODE 2031 +#define SCI_STARTSTYLING 2032 +#define SCI_SETSTYLING 2033 +#define SCI_GETBUFFEREDDRAW 2034 +#define SCI_SETBUFFEREDDRAW 2035 +#define SCI_SETTABWIDTH 2036 +#define SCI_GETTABWIDTH 2121 +#define SC_CP_UTF8 65001 +#define SCI_SETCODEPAGE 2037 +#define SCI_SETUSEPALETTE 2039 +#define MARKER_MAX 31 +#define SC_MARK_CIRCLE 0 +#define SC_MARK_ROUNDRECT 1 +#define SC_MARK_ARROW 2 +#define SC_MARK_SMALLRECT 3 +#define SC_MARK_SHORTARROW 4 +#define SC_MARK_EMPTY 5 +#define SC_MARK_ARROWDOWN 6 +#define SC_MARK_MINUS 7 +#define SC_MARK_PLUS 8 +#define SC_MARK_VLINE 9 +#define SC_MARK_LCORNER 10 +#define SC_MARK_TCORNER 11 +#define SC_MARK_BOXPLUS 12 +#define SC_MARK_BOXPLUSCONNECTED 13 +#define SC_MARK_BOXMINUS 14 +#define SC_MARK_BOXMINUSCONNECTED 15 +#define SC_MARK_LCORNERCURVE 16 +#define SC_MARK_TCORNERCURVE 17 +#define SC_MARK_CIRCLEPLUS 18 +#define SC_MARK_CIRCLEPLUSCONNECTED 19 +#define SC_MARK_CIRCLEMINUS 20 +#define SC_MARK_CIRCLEMINUSCONNECTED 21 +#define SC_MARKNUM_FOLDEREND 25 +#define SC_MARKNUM_FOLDEROPENMID 26 +#define SC_MARKNUM_FOLDERMIDTAIL 27 +#define SC_MARKNUM_FOLDERTAIL 28 +#define SC_MARKNUM_FOLDERSUB 29 +#define SC_MARKNUM_FOLDER 30 +#define SC_MARKNUM_FOLDEROPEN 31 +#define SCI_MARKERDEFINE 2040 +#define SCI_MARKERSETFORE 2041 +#define SCI_MARKERSETBACK 2042 +#define SCI_MARKERADD 2043 +#define SCI_MARKERDELETE 2044 +#define SCI_MARKERDELETEALL 2045 +#define SCI_MARKERGET 2046 +#define SCI_MARKERNEXT 2047 +#define SCI_MARKERPREVIOUS 2048 +#define SC_MARGIN_SYMBOL 0 +#define SC_MARGIN_NUMBER 1 +#define SCI_SETMARGINTYPEN 2240 +#define SCI_GETMARGINTYPEN 2241 +#define SCI_SETMARGINWIDTHN 2242 +#define SCI_GETMARGINWIDTHN 2243 +#define SCI_SETMARGINMASKN 2244 +#define SCI_GETMARGINMASKN 2245 +#define SCI_SETMARGINSENSITIVEN 2246 +#define SCI_GETMARGINSENSITIVEN 2247 +#define STYLE_DEFAULT 32 +#define STYLE_LINENUMBER 33 +#define STYLE_BRACELIGHT 34 +#define STYLE_BRACEBAD 35 +#define STYLE_CONTROLCHAR 36 +#define STYLE_INDENTGUIDE 37 +#define STYLE_MAX 127 +#define SC_CHARSET_ANSI 0 +#define SC_CHARSET_DEFAULT 1 +#define SC_CHARSET_BALTIC 186 +#define SC_CHARSET_CHINESEBIG5 136 +#define SC_CHARSET_EASTEUROPE 238 +#define SC_CHARSET_GB2312 134 +#define SC_CHARSET_GREEK 161 +#define SC_CHARSET_HANGUL 129 +#define SC_CHARSET_MAC 77 +#define SC_CHARSET_OEM 255 +#define SC_CHARSET_RUSSIAN 204 +#define SC_CHARSET_SHIFTJIS 128 +#define SC_CHARSET_SYMBOL 2 +#define SC_CHARSET_TURKISH 162 +#define SC_CHARSET_JOHAB 130 +#define SC_CHARSET_HEBREW 177 +#define SC_CHARSET_ARABIC 178 +#define SC_CHARSET_VIETNAMESE 163 +#define SC_CHARSET_THAI 222 +#define SCI_STYLECLEARALL 2050 +#define SCI_STYLESETFORE 2051 +#define SCI_STYLESETBACK 2052 +#define SCI_STYLESETBOLD 2053 +#define SCI_STYLESETITALIC 2054 +#define SCI_STYLESETSIZE 2055 +#define SCI_STYLESETFONT 2056 +#define SCI_STYLESETEOLFILLED 2057 +#define SCI_STYLERESETDEFAULT 2058 +#define SCI_STYLESETUNDERLINE 2059 +#define SC_CASE_MIXED 0 +#define SC_CASE_UPPER 1 +#define SC_CASE_LOWER 2 +#define SCI_STYLESETCASE 2060 +#define SCI_STYLESETCHARACTERSET 2066 +#define SCI_SETSELFORE 2067 +#define SCI_SETSELBACK 2068 +#define SCI_SETCARETFORE 2069 +#define SCI_ASSIGNCMDKEY 2070 +#define SCI_CLEARCMDKEY 2071 +#define SCI_CLEARALLCMDKEYS 2072 +#define SCI_SETSTYLINGEX 2073 +#define SCI_STYLESETVISIBLE 2074 +#define SCI_GETCARETPERIOD 2075 +#define SCI_SETCARETPERIOD 2076 +#define SCI_SETWORDCHARS 2077 +#define SCI_BEGINUNDOACTION 2078 +#define SCI_ENDUNDOACTION 2079 +#define INDIC_MAX 7 +#define INDIC_PLAIN 0 +#define INDIC_SQUIGGLE 1 +#define INDIC_TT 2 +#define INDIC_DIAGONAL 3 +#define INDIC_STRIKE 4 +#define INDIC0_MASK 32 +#define INDIC1_MASK 64 +#define INDIC2_MASK 128 +#define INDICS_MASK INDIC0_MASK | INDIC1_MASK | INDIC2_MASK +#define SCI_INDICSETSTYLE 2080 +#define SCI_INDICGETSTYLE 2081 +#define SCI_INDICSETFORE 2082 +#define SCI_INDICGETFORE 2083 +#define SCI_SETSTYLEBITS 2090 +#define SCI_GETSTYLEBITS 2091 +#define SCI_SETLINESTATE 2092 +#define SCI_GETLINESTATE 2093 +#define SCI_GETMAXLINESTATE 2094 +#define SCI_GETCARETLINEVISIBLE 2095 +#define SCI_SETCARETLINEVISIBLE 2096 +#define SCI_GETCARETLINEBACK 2097 +#define SCI_SETCARETLINEBACK 2098 +#define SCI_AUTOCSHOW 2100 +#define SCI_AUTOCCANCEL 2101 +#define SCI_AUTOCACTIVE 2102 +#define SCI_AUTOCPOSSTART 2103 +#define SCI_AUTOCCOMPLETE 2104 +#define SCI_AUTOCSTOPS 2105 +#define SCI_AUTOCSETSEPARATOR 2106 +#define SCI_AUTOCGETSEPARATOR 2107 +#define SCI_AUTOCSELECT 2108 +#define SCI_AUTOCSETCANCELATSTART 2110 +#define SCI_AUTOCGETCANCELATSTART 2111 +#define SCI_AUTOCSETFILLUPS 2112 +#define SCI_AUTOCSETCHOOSESINGLE 2113 +#define SCI_AUTOCGETCHOOSESINGLE 2114 +#define SCI_AUTOCSETIGNORECASE 2115 +#define SCI_AUTOCGETIGNORECASE 2116 +#define SCI_USERLISTSHOW 2117 +#define SCI_AUTOCSETAUTOHIDE 2118 +#define SCI_AUTOCGETAUTOHIDE 2119 +#define SCI_SETINDENT 2122 +#define SCI_GETINDENT 2123 +#define SCI_SETUSETABS 2124 +#define SCI_GETUSETABS 2125 +#define SCI_SETLINEINDENTATION 2126 +#define SCI_GETLINEINDENTATION 2127 +#define SCI_GETLINEINDENTPOSITION 2128 +#define SCI_GETCOLUMN 2129 +#define SCI_SETHSCROLLBAR 2130 +#define SCI_GETHSCROLLBAR 2131 +#define SCI_SETINDENTATIONGUIDES 2132 +#define SCI_GETINDENTATIONGUIDES 2133 +#define SCI_SETHIGHLIGHTGUIDE 2134 +#define SCI_GETHIGHLIGHTGUIDE 2135 +#define SCI_GETLINEENDPOSITION 2136 +#define SCI_GETCODEPAGE 2137 +#define SCI_GETCARETFORE 2138 +#define SCI_GETUSEPALETTE 2139 +#define SCI_GETREADONLY 2140 +#define SCI_SETCURRENTPOS 2141 +#define SCI_SETSELECTIONSTART 2142 +#define SCI_GETSELECTIONSTART 2143 +#define SCI_SETSELECTIONEND 2144 +#define SCI_GETSELECTIONEND 2145 +#define SCI_SETPRINTMAGNIFICATION 2146 +#define SCI_GETPRINTMAGNIFICATION 2147 +#define SC_PRINT_NORMAL 0 +#define SC_PRINT_INVERTLIGHT 1 +#define SC_PRINT_BLACKONWHITE 2 +#define SC_PRINT_COLOURONWHITE 3 +#define SC_PRINT_COLOURONWHITEDEFAULTBG 4 +#define SCI_SETPRINTCOLOURMODE 2148 +#define SCI_GETPRINTCOLOURMODE 2149 +#define SCFIND_WHOLEWORD 2 +#define SCFIND_MATCHCASE 4 +#define SCFIND_WORDSTART 0x00100000 +#define SCFIND_REGEXP 0x00200000 +#define SCI_FINDTEXT 2150 +#define SCI_FORMATRANGE 2151 +#define SCI_GETFIRSTVISIBLELINE 2152 +#define SCI_GETLINE 2153 +#define SCI_GETLINECOUNT 2154 +#define SCI_SETMARGINLEFT 2155 +#define SCI_GETMARGINLEFT 2156 +#define SCI_SETMARGINRIGHT 2157 +#define SCI_GETMARGINRIGHT 2158 +#define SCI_GETMODIFY 2159 +#define SCI_SETSEL 2160 +#define SCI_GETSELTEXT 2161 +#define SCI_GETTEXTRANGE 2162 +#define SCI_HIDESELECTION 2163 +#define SCI_POINTXFROMPOSITION 2164 +#define SCI_POINTYFROMPOSITION 2165 +#define SCI_LINEFROMPOSITION 2166 +#define SCI_POSITIONFROMLINE 2167 +#define SCI_LINESCROLL 2168 +#define SCI_SCROLLCARET 2169 +#define SCI_REPLACESEL 2170 +#define SCI_SETREADONLY 2171 +#define SCI_NULL 2172 +#define SCI_CANPASTE 2173 +#define SCI_CANUNDO 2174 +#define SCI_EMPTYUNDOBUFFER 2175 +#define SCI_UNDO 2176 +#define SCI_CUT 2177 +#define SCI_COPY 2178 +#define SCI_PASTE 2179 +#define SCI_CLEAR 2180 +#define SCI_SETTEXT 2181 +#define SCI_GETTEXT 2182 +#define SCI_GETTEXTLENGTH 2183 +#define SCI_GETDIRECTFUNCTION 2184 +#define SCI_GETDIRECTPOINTER 2185 +#define SCI_SETOVERTYPE 2186 +#define SCI_GETOVERTYPE 2187 +#define SCI_SETCARETWIDTH 2188 +#define SCI_GETCARETWIDTH 2189 +#define SCI_SETTARGETSTART 2190 +#define SCI_GETTARGETSTART 2191 +#define SCI_SETTARGETEND 2192 +#define SCI_GETTARGETEND 2193 +#define SCI_REPLACETARGET 2194 +#define SCI_REPLACETARGETRE 2195 +#define SCI_SEARCHINTARGET 2197 +#define SCI_SETSEARCHFLAGS 2198 +#define SCI_GETSEARCHFLAGS 2199 +#define SCI_CALLTIPSHOW 2200 +#define SCI_CALLTIPCANCEL 2201 +#define SCI_CALLTIPACTIVE 2202 +#define SCI_CALLTIPPOSSTART 2203 +#define SCI_CALLTIPSETHLT 2204 +#define SCI_CALLTIPSETBACK 2205 +#define SCI_VISIBLEFROMDOCLINE 2220 +#define SCI_DOCLINEFROMVISIBLE 2221 +#define SC_FOLDLEVELBASE 0x400 +#define SC_FOLDLEVELWHITEFLAG 0x1000 +#define SC_FOLDLEVELHEADERFLAG 0x2000 +#define SC_FOLDLEVELNUMBERMASK 0x0FFF +#define SCI_SETFOLDLEVEL 2222 +#define SCI_GETFOLDLEVEL 2223 +#define SCI_GETLASTCHILD 2224 +#define SCI_GETFOLDPARENT 2225 +#define SCI_SHOWLINES 2226 +#define SCI_HIDELINES 2227 +#define SCI_GETLINEVISIBLE 2228 +#define SCI_SETFOLDEXPANDED 2229 +#define SCI_GETFOLDEXPANDED 2230 +#define SCI_TOGGLEFOLD 2231 +#define SCI_ENSUREVISIBLE 2232 +#define SCI_SETFOLDFLAGS 2233 +#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234 +#define SCI_SETTABINDENTS 2260 +#define SCI_GETTABINDENTS 2261 +#define SCI_SETBACKSPACEUNINDENTS 2262 +#define SCI_GETBACKSPACEUNINDENTS 2263 +#define SC_TIME_FOREVER 10000000 +#define SCI_SETMOUSEDWELLTIME 2264 +#define SCI_GETMOUSEDWELLTIME 2265 +#define SCI_LINEDOWN 2300 +#define SCI_LINEDOWNEXTEND 2301 +#define SCI_LINEUP 2302 +#define SCI_LINEUPEXTEND 2303 +#define SCI_CHARLEFT 2304 +#define SCI_CHARLEFTEXTEND 2305 +#define SCI_CHARRIGHT 2306 +#define SCI_CHARRIGHTEXTEND 2307 +#define SCI_WORDLEFT 2308 +#define SCI_WORDLEFTEXTEND 2309 +#define SCI_WORDRIGHT 2310 +#define SCI_WORDRIGHTEXTEND 2311 +#define SCI_HOME 2312 +#define SCI_HOMEEXTEND 2313 +#define SCI_LINEEND 2314 +#define SCI_LINEENDEXTEND 2315 +#define SCI_DOCUMENTSTART 2316 +#define SCI_DOCUMENTSTARTEXTEND 2317 +#define SCI_DOCUMENTEND 2318 +#define SCI_DOCUMENTENDEXTEND 2319 +#define SCI_PAGEUP 2320 +#define SCI_PAGEUPEXTEND 2321 +#define SCI_PAGEDOWN 2322 +#define SCI_PAGEDOWNEXTEND 2323 +#define SCI_EDITTOGGLEOVERTYPE 2324 +#define SCI_CANCEL 2325 +#define SCI_DELETEBACK 2326 +#define SCI_TAB 2327 +#define SCI_BACKTAB 2328 +#define SCI_NEWLINE 2329 +#define SCI_FORMFEED 2330 +#define SCI_VCHOME 2331 +#define SCI_VCHOMEEXTEND 2332 +#define SCI_ZOOMIN 2333 +#define SCI_ZOOMOUT 2334 +#define SCI_DELWORDLEFT 2335 +#define SCI_DELWORDRIGHT 2336 +#define SCI_LINECUT 2337 +#define SCI_LINEDELETE 2338 +#define SCI_LINETRANSPOSE 2339 +#define SCI_LOWERCASE 2340 +#define SCI_UPPERCASE 2341 +#define SCI_LINESCROLLDOWN 2342 +#define SCI_LINESCROLLUP 2343 +#define SCI_MOVECARETINSIDEVIEW 2401 +#define SCI_LINELENGTH 2350 +#define SCI_BRACEHIGHLIGHT 2351 +#define SCI_BRACEBADLIGHT 2352 +#define SCI_BRACEMATCH 2353 +#define SCI_GETVIEWEOL 2355 +#define SCI_SETVIEWEOL 2356 +#define SCI_GETDOCPOINTER 2357 +#define SCI_SETDOCPOINTER 2358 +#define SCI_SETMODEVENTMASK 2359 +#define EDGE_NONE 0 +#define EDGE_LINE 1 +#define EDGE_BACKGROUND 2 +#define SCI_GETEDGECOLUMN 2360 +#define SCI_SETEDGECOLUMN 2361 +#define SCI_GETEDGEMODE 2362 +#define SCI_SETEDGEMODE 2363 +#define SCI_GETEDGECOLOUR 2364 +#define SCI_SETEDGECOLOUR 2365 +#define SCI_SEARCHANCHOR 2366 +#define SCI_SEARCHNEXT 2367 +#define SCI_SEARCHPREV 2368 +#define CARET_SLOP 0x01 +#define CARET_CENTER 0x02 +#define CARET_STRICT 0x04 +#define CARET_XEVEN 0x08 +#define CARET_XJUMPS 0x10 +#define SCI_SETCARETPOLICY 2369 +#define SCI_LINESONSCREEN 2370 +#define SCI_USEPOPUP 2371 +#define SCI_SELECTIONISRECTANGLE 2372 +#define SCI_SETZOOM 2373 +#define SCI_GETZOOM 2374 +#define SCI_CREATEDOCUMENT 2375 +#define SCI_ADDREFDOCUMENT 2376 +#define SCI_RELEASEDOCUMENT 2377 +#define SCI_GETMODEVENTMASK 2378 +#define SCI_SETFOCUS 2380 +#define SCI_GETFOCUS 2381 +#define SCI_SETSTATUS 2382 +#define SCI_GETSTATUS 2383 +#define SCI_SETMOUSEDOWNCAPTURES 2384 +#define SCI_GETMOUSEDOWNCAPTURES 2385 +#define SC_CURSORNORMAL -1 +#define SC_CURSORWAIT 3 +#define SCI_SETCURSOR 2386 +#define SCI_GETCURSOR 2387 +#define SCI_WORDPARTLEFT 2390 +#define SCI_WORDPARTLEFTEXTEND 2391 +#define SCI_WORDPARTRIGHT 2392 +#define SCI_WORDPARTRIGHTEXTEND 2393 +#define VISIBLE_SLOP 0x01 +#define VISIBLE_STRICT 0x04 +#define SCI_SETVISIBLEPOLICY 2394 +#define SCI_DELLINELEFT 2395 +#define SCI_DELLINERIGHT 2396 +#define SCI_GRABFOCUS 2400 +#define SCI_STARTRECORD 3001 +#define SCI_STOPRECORD 3002 +#define SCI_SETLEXER 4001 +#define SCI_GETLEXER 4002 +#define SCI_COLOURISE 4003 +#define SCI_SETPROPERTY 4004 +#define SCI_SETKEYWORDS 4005 +#define SCI_SETLEXERLANGUAGE 4006 +#define SC_MOD_INSERTTEXT 0x1 +#define SC_MOD_DELETETEXT 0x2 +#define SC_MOD_CHANGESTYLE 0x4 +#define SC_MOD_CHANGEFOLD 0x8 +#define SC_PERFORMED_USER 0x10 +#define SC_PERFORMED_UNDO 0x20 +#define SC_PERFORMED_REDO 0x40 +#define SC_LASTSTEPINUNDOREDO 0x100 +#define SC_MOD_CHANGEMARKER 0x200 +#define SC_MOD_BEFOREINSERT 0x400 +#define SC_MOD_BEFOREDELETE 0x800 +#define SC_MODEVENTMASKALL 0xF77 +#define SCEN_CHANGE 768 +#define SCEN_SETFOCUS 512 +#define SCEN_KILLFOCUS 256 +#define SCK_DOWN 300 +#define SCK_UP 301 +#define SCK_LEFT 302 +#define SCK_RIGHT 303 +#define SCK_HOME 304 +#define SCK_END 305 +#define SCK_PRIOR 306 +#define SCK_NEXT 307 +#define SCK_DELETE 308 +#define SCK_INSERT 309 +#define SCK_ESCAPE 7 +#define SCK_BACK 8 +#define SCK_TAB 9 +#define SCK_RETURN 13 +#define SCK_ADD 310 +#define SCK_SUBTRACT 311 +#define SCK_DIVIDE 312 +#define SCMOD_SHIFT 1 +#define SCMOD_CTRL 2 +#define SCMOD_ALT 4 +#define SCN_STYLENEEDED 2000 +#define SCN_CHARADDED 2001 +#define SCN_SAVEPOINTREACHED 2002 +#define SCN_SAVEPOINTLEFT 2003 +#define SCN_MODIFYATTEMPTRO 2004 +#define SCN_KEY 2005 +#define SCN_DOUBLECLICK 2006 +#define SCN_UPDATEUI 2007 +#define SCN_CHECKBRACE 2007 +#define SCN_MODIFIED 2008 +#define SCN_MACRORECORD 2009 +#define SCN_MARGINCLICK 2010 +#define SCN_NEEDSHOWN 2011 +#define SCN_POSCHANGED 2012 +#define SCN_PAINTED 2013 +#define SCN_USERLISTSELECTION 2014 +#define SCN_URIDROPPED 2015 +#define SCN_DWELLSTART 2016 +#define SCN_DWELLEND 2017 +//--Autogenerated -- end of section automatically generated from Scintilla.iface + +// Optional module for macro recording +#ifdef MACRO_SUPPORT +typedef void (tMacroRecorder)(unsigned int iMessage, unsigned long wParam, + long lParam, void *userData); +#endif + +// These structures are defined to be exactly the same shape as the Win32 +// CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs. +// So older code that treats Scintilla as a RichEdit will work. + +struct CharacterRange { + long cpMin; + long cpMax; +}; + +struct TextRange { + struct CharacterRange chrg; + char *lpstrText; +}; + +struct TextToFind { + struct CharacterRange chrg; + char *lpstrText; + struct CharacterRange chrgText; +}; + +#ifdef PLATFORM_H + +// This structure is used in printing and requires some of the graphics types +// from Platform.h. Not needed by most client code. + +struct RangeToFormat { + SurfaceID hdc; + SurfaceID hdcTarget; + PRectangle rc; + PRectangle rcPage; + CharacterRange chrg; +}; + +#endif + +struct NotifyHeader { + // hwndFrom is really an environment specifc window handle or pointer + // but most clients of Scintilla.h do not have this type visible. + //WindowID hwndFrom; + void *hwndFrom; + unsigned int idFrom; + unsigned int code; +}; + +struct SCNotification { + struct NotifyHeader nmhdr; + int position; // SCN_STYLENEEDED, SCN_MODIFIED, SCN_DWELLSTART, SCN_DWELLEND + int ch; // SCN_CHARADDED, SCN_KEY + int modifiers; // SCN_KEY + int modificationType; // SCN_MODIFIED + const char *text; // SCN_MODIFIED + int length; // SCN_MODIFIED + int linesAdded; // SCN_MODIFIED +#ifdef MACRO_SUPPORT + int message; // SCN_MACRORECORD + uptr_t wParam; // SCN_MACRORECORD + sptr_t lParam; // SCN_MACRORECORD +#endif + int line; // SCN_MODIFIED + int foldLevelNow; // SCN_MODIFIED + int foldLevelPrev; // SCN_MODIFIED + int margin; // SCN_MARGINCLICK + int listType; // SCN_USERLISTSELECTION + int x; // SCN_DWELLSTART, SCN_DWELLEND + int y; // SCN_DWELLSTART, SCN_DWELLEND +}; + +#define SC_MASK_FOLDERS ((1< +#include +#include "commctrl.h" +#include "commdlg.h" +#include "editor.h" +#include "rsrc.h" + +extern CMessageBox MsgBox; + +int Minimum(int a, int b); +int Maximum(int a, int b); + +int Minimum(int a, int b){ + if (a < b) + return a; + else + return b; +} + +int Maximum(int a, int b){ + if (a > b) + return a; + else + return b; +} + +void EnsureRangeVisible(HWND hwndCtrl, int posStart, int posEnd, bool enforcePolicy){ + int lineStart = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Minimum(posStart, posEnd), 0); + int lineEnd = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Maximum(posStart, posEnd), 0); + for (int line = lineStart; line <= lineEnd; line++){ + SendMessage(hwndCtrl, + enforcePolicy ? SCI_ENSUREVISIBLEENFORCEPOLICY : SCI_ENSUREVISIBLE, line, 0); + } +} + +int LengthDocument(HWND hwndCtrl){ +return SendMessage(hwndCtrl, SCI_GETLENGTH, 0, 0); +} + +CharacterRange GetSelection(HWND hwndCtrl){ + CharacterRange crange; + crange.cpMin = SendMessage(hwndCtrl, SCI_GETSELECTIONSTART, 0, 0); + crange.cpMax = SendMessage(hwndCtrl, SCI_GETSELECTIONEND, 0, 0); +return crange; +} + + +/******************************************************************** +* Class: CChooseFontDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CChooseFontDlg::CChooseFontDlg(){ + ZeroMemory(&lf, sizeof(LOGFONT)); +/* lf.lfHeight; + lf.lfWidth; + lf.lfEscapement; + lf.lfOrientation; + lf.lfWeight; + lf.lfItalic; + lf.lfUnderline; + lf.lfStrikeOut; + lf.lfCharSet; + lf.lfOutPrecision; + lf.lfClipPrecision; + lf.lfQuality; + lf.lfPitchAndFamily; + lf.lfFaceName[LF_FACESIZE];*/ + + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = 0; + cf.hDC = NULL; + cf.lpLogFont = &lf;//&(Profile.LogFont); + cf.iPointSize = 0; + cf.Flags = /*CF_INITTOLOGFONTSTRUCT + |*/ CF_SCREENFONTS | CF_EFFECTS + /*| CF_ENABLEHOOK*/; + cf.rgbColors = 0;//Profile.rgbForeColor; + cf.lCustData = 0; + cf.lpfnHook = NULL; + cf.lpTemplateName = NULL; + cf.hInstance = NULL; + cf.lpszStyle = NULL; + cf.nFontType = SCREEN_FONTTYPE; + cf.nSizeMin = 0; + cf.nSizeMax = 0; +} + +CChooseFontDlg::~CChooseFontDlg(){ +} + +bool CChooseFontDlg::Create(CWindow * pWindow){ + cf.hwndOwner = pWindow->_hWnd; +return ChooseFont(&cf); +} + + +/*bool ChooseNewFont(HWND hWndListBox){ + static CHOOSEFONT cf; + static BOOL bFirstTime = TRUE; + HFONT hFont; + if(bFirstTime){ + bFirstTime = false; + } + if(ChooseFont(&cf)){ + HDC hDC; + hFont = CreateFontIndirect( &(Profile.LogFont) ); + hDC = GetDC( hWndListBox ); + SelectObject( hDC, hFont ); + Profile.rgbForeColor = cf.rgbColors; + InvalidateRect( hWndListBox, NULL, TRUE ); + SendMessage( hWndListBox, WM_CTLCOLORLISTBOX, (DWORD) hDC, (LONG) hWndListBox ); + SendMessage( hWndListBox, WM_SETFONT, (DWORD) hFont, TRUE ); + ReleaseDC( hWndListBox, hDC ); + } +return true; +}*/ + + +/******************************************************************** +* Class: CFindReplaceDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CFindReplaceDlg::CFindReplaceDlg(){ + pEditor = NULL; + hEditor = 0; + resId = 0; + *findWhat = '\0'; + *replaceWhat = '\0'; + + bWholeWord = false; + bMatchCase = true; + bRegExp = false; + bWrapFind = false; + bUnSlash = false; + bReverseFind = false; + bHavefound = false; +} + +CFindReplaceDlg::~CFindReplaceDlg(){ +} + +HWND CFindReplaceDlg::Find(CScintilla * pEditor){ + if (_hWnd || !pEditor) + return 0; +return CreateParam(pEditor, IDD_FIND, (long) IDD_FIND); +} + +HWND CFindReplaceDlg::Replace(CScintilla * pEditor){ + if (_hWnd || !pEditor) + return 0; +return CreateParam(pEditor, IDD_REPLACE, (long) IDD_REPLACE); +} + +LRESULT CALLBACK CFindReplaceDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CFindReplaceDlg::OnInitDialog(HWND, LPARAM lInitParam){ + // Set pointers. + pEditor = (CEditor *) _pParent; + if (pEditor == NULL) + return TRUE; + + hEditor = pEditor->_hWnd; + resId = lInitParam; + + hFindWhat = GetItem(IDC_FINDWHAT); + hWholeWord = GetItem(IDC_WHOLEWORD); + hMatchCase = GetItem(IDC_MATCHCASE); + hRegExp = GetItem(IDC_REGEXP); + hWrap = GetItem(IDC_WRAP); + hUnSlash = GetItem(IDC_UNSLASH); + + if (resId == IDD_FIND) + return Find_OnInitDialog(); + else if (resId == IDD_REPLACE) + return Replace_OnInitDialog(); +return FALSE; +} + +BOOL CFindReplaceDlg::Find_OnInitDialog(void){ + + hUp = GetItem(IDC_DIRECTIONUP); + hDown = GetItem(IDC_DIRECTIONDOWN); + + SetItemText(hFindWhat, findWhat); + //FillComboFromMemory(wFindWhat, memFinds); + if (bWholeWord) + ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0); + if (bMatchCase) + ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0); + if (bRegExp) + ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0); + if (bWrapFind) + ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0); + if (bUnSlash) + ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0); + + if (bReverseFind) { + ::SendMessage(hUp, BM_SETCHECK, BST_CHECKED, 0); + } else { + ::SendMessage(hDown, BM_SETCHECK, BST_CHECKED, 0); + } +return TRUE; +} + +BOOL CFindReplaceDlg::Replace_OnInitDialog(void){ + SetItemText(hFindWhat, findWhat); + //FillComboFromMemory(wFindWhat, sci->memFinds); + + hReplaceWith = GetItem(IDC_REPLACEWITH); + SetItemText(hReplaceWith, replaceWhat); + //FillComboFromMemory(wReplaceWith, sci->memReplaces); + + if (bWholeWord) + ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0); + if (bMatchCase) + ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0); + if (bRegExp) + ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0); + if (bWrapFind) + ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0); + if (bUnSlash) + ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0); + if ((findWhat) != '\0'){ + ::SetFocus(hReplaceWith); + return FALSE; + } +return TRUE; +} + +BOOL CFindReplaceDlg::OnCommand(WORD, WORD wID, HWND){ + if (resId == IDD_FIND) + return Find_OnCommand(wID); + else if (resId == IDD_REPLACE) + return Replace_OnCommand(wID); +return FALSE; +} + +BOOL CFindReplaceDlg::Find_OnCommand(WORD wID){ + switch (wID){ + case IDOK: + char s[200]; + GetItemText(hFindWhat, s, sizeof(s)); + strcpy(findWhat, s); + //memFinds.Insert(s); + bWholeWord = BST_CHECKED == + ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0); + bMatchCase = BST_CHECKED == + ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0); + bRegExp = BST_CHECKED == + ::SendMessage(hRegExp, BM_GETCHECK, 0, 0); + bWrapFind = BST_CHECKED == + ::SendMessage(hWrap, BM_GETCHECK, 0, 0); + bUnSlash = BST_CHECKED == + ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0); + bReverseFind = BST_CHECKED == + ::SendMessage(hUp, BM_GETCHECK, 0, 0); + + FindNext(bReverseFind, true); + return TRUE; + + case IDCANCEL: + EndDlg(IDCANCEL); + return FALSE; + } +return FALSE; +} + +BOOL CFindReplaceDlg::Replace_OnCommand(WORD wID){ + if (wID == IDCANCEL){ + EndDlg(IDCANCEL); + return FALSE; + }else{ + return HandleReplaceCommand(wID); + } +return FALSE; +} + +void CFindReplaceDlg::FindNext(bool reverseDirection, bool showWarnings){ + if (!hEditor){ + MsgBox.DisplayWarning("Can't get editor handle"); + return; + } + + if (!findWhat[0]) { // nothing to found + //Find(hEditor); + return; + } + char findTarget[FR_MAX_LEN + 1]; + strcpy(findTarget, findWhat); + + // for C conversions -> int lenFind = UnSlashAsNeeded(findTarget, unSlash, regExp); + int lenFind = strlen(findTarget); // normal return of UnSlashAsNeeded + + if (lenFind == 0) + return; + + CharacterRange cr = GetSelection(hEditor); + int startPosition = cr.cpMax; + int endPosition = LengthDocument(hEditor); + + if (reverseDirection){ + startPosition = cr.cpMin - 1; + endPosition = 0; + } + + int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) | + (bMatchCase ? SCFIND_MATCHCASE : 0) | + (bRegExp ? SCFIND_REGEXP : 0); + + ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); + ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0); + int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget); + + if (posFind == -1 && bWrapFind){ // not found with wrapFind + + // Failed to find in indicated direction + // so search from the beginning (forward) or from the end (reverse) + // unless wrapFind is false + if (reverseDirection){ + startPosition = LengthDocument(hEditor); + endPosition = 0; + } else { + startPosition = 0; + endPosition = LengthDocument(hEditor); + } + ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); + posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget); + } + if (posFind == -1){ // not found + bHavefound = false; + if (showWarnings){ + + /*warn that not found + WarnUser(warnNotFound);*/ + + if (strlen(findWhat) > FR_MAX_LEN) + findWhat[FR_MAX_LEN] = '\0'; + char msg[FR_MAX_LEN + 50]; + strcpy(msg, "Cannot find the string \""); + strcat(msg, findWhat); + strcat(msg, "\"."); + if (_hWnd){ + MsgBox.DisplayWarning(msg); + }else{ + MessageBox(0, msg, "Message", MB_OK); + } + } + }else{ // found + bHavefound = true; + int start = ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0); + int end = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0); + EnsureRangeVisible(hEditor, start, end, true); + ::SendMessage(hEditor, SCI_SETSEL, start, end); + } +} + +BOOL CFindReplaceDlg::HandleReplaceCommand(int cmd){ + if (!hEditor){ + MsgBox.DisplayWarning("Can't get editor handle"); + return false; + } + + if ((cmd == IDOK) || (cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) { + GetItemText(hFindWhat, findWhat, sizeof(findWhat)); + //props.Set("find.what", findWhat); + //memFinds.Insert(findWhat); + + bWholeWord = BST_CHECKED == + ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0); + bMatchCase = BST_CHECKED == + ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0); + bRegExp = BST_CHECKED == + ::SendMessage(hRegExp, BM_GETCHECK, 0, 0); + bWrapFind = BST_CHECKED == + ::SendMessage(hWrap, BM_GETCHECK, 0, 0); + bUnSlash = BST_CHECKED == + ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0); + } + if ((cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) { + GetItemText(hReplaceWith, replaceWhat, sizeof(replaceWhat)); + //memReplaces.Insert(replaceWhat); + } + + if (cmd == IDOK) { + FindNext(bReverseFind, true); // Find next + } else if (cmd == IDC_REPLACE) { + if (bHavefound){ + ReplaceOnce(); + } else { + CharacterRange crange = GetSelection(hEditor); + ::SendMessage(hEditor, SCI_SETSEL, crange.cpMin, crange.cpMin); + FindNext(bReverseFind, true); + if (bHavefound){ + ReplaceOnce(); + } + } + } else if ((cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)){ + ReplaceAll(cmd == IDC_REPLACEINSEL); + } +return TRUE; +} + +void CFindReplaceDlg::ReplaceOnce(void){ + if (bHavefound){ + char replaceTarget[FR_MAX_LEN + 1]; + strcpy(replaceTarget, replaceWhat); + // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp); + int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded + + CharacterRange cr = GetSelection(hEditor); + ::SendMessage(hEditor, SCI_SETTARGETSTART, cr.cpMin, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, cr.cpMax, 0); + int lenReplaced = replaceLen; + if (bRegExp) + lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget); + else // Allow \0 in replacement + ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget); + ::SendMessage(hEditor, SCI_SETSEL, cr.cpMin + lenReplaced, cr.cpMin); + bHavefound = false; + } + FindNext(bReverseFind, true); +} + +void CFindReplaceDlg::ReplaceAll(bool inSelection){ + char findTarget[FR_MAX_LEN + 1]; + strcpy(findTarget, findWhat); + + // for C conversions -> int findLen = UnSlashAsNeeded(findTarget, unSlash, regExp); + int findLen = strlen(findTarget); // normal return of UnSlashAsNeeded + + if (findLen == 0) { + MessageBox(_hWnd, "Find string for \"Replace All\" must not be empty.", "Message", MB_OK | MB_ICONWARNING); + return; + } + + CharacterRange cr = GetSelection(hEditor); + int startPosition = cr.cpMin; + int endPosition = cr.cpMax; + if (inSelection) { + if (startPosition == endPosition) { + MessageBox(_hWnd, "Selection for \"Replace in Selection\" must not be empty.", "Message", MB_OK | MB_ICONWARNING); + return; + } + } else { + endPosition = LengthDocument(hEditor); + if (bWrapFind) { + // Whole document + startPosition = 0; + } + // If not wrapFind, replace all only from caret to end of document + } + + char replaceTarget[FR_MAX_LEN + 1]; + strcpy(replaceTarget, replaceWhat); + + // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp); + int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded + + int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) | + (bMatchCase ? SCFIND_MATCHCASE : 0) | + (bRegExp ? SCFIND_REGEXP : 0); + ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); + ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0); + int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget); + if ((findLen == 1) && bRegExp && (findTarget[0] == '^')) { + // Special case for replace all start of line so it hits the first line + posFind = startPosition; + ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, startPosition, 0); + } + if ((posFind != -1) && (posFind <= endPosition)) { + int lastMatch = posFind; + ::SendMessage(hEditor, SCI_BEGINUNDOACTION, 0, 0); + while (posFind != -1) { + int lenTarget = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0) - ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0); + int lenReplaced = replaceLen; + if (bRegExp) + lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget); + else + ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget); + // Modify for change caused by replacement + endPosition += lenReplaced - lenTarget; + lastMatch = posFind + lenReplaced; + // For the special cases of start of line and end of line + // Something better could be done but there are too many special cases + if (lenTarget <= 0) + lastMatch++; + ::SendMessage(hEditor, SCI_SETTARGETSTART, lastMatch, 0); + ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); + posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget); + } + if (inSelection) + ::SendMessage(hEditor, SCI_SETSEL, startPosition, endPosition); + else + ::SendMessage(hEditor, SCI_SETSEL, lastMatch, lastMatch); + ::SendMessage(hEditor, SCI_ENDUNDOACTION, 0, 0); + } else { + if (strlen(findWhat) > FR_MAX_LEN) + findWhat[FR_MAX_LEN] = '\0'; + char msg[FR_MAX_LEN + 50]; + strcpy(msg, "No replacements because string \""); + strcat(msg, findWhat); + strcat(msg, "\" was not present."); + MessageBox(_hWnd, msg, "Message", MB_OK | MB_ICONWARNING); + } +} + + +/******************************************************************** +* Class: CEditor. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CEditor::CEditor(){ + caretPos = 1; +} + +CEditor::~CEditor(){ +} + +void CEditor::LoadFile(CFileItem * file){ + if (!file || !_hWnd) + return; + + if (file->nFileOffset == 0) + return; // Untitled file. + + SetLexer(file->type); + ::SendMessage(_hWnd, SCI_CANCEL, 0, 0); + ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 0, 0); + + FILE *fp = fopen(file->szFileName, "rb"); + if (fp){ + char data[blockSize]; + int lenFile = fread(data, 1, sizeof(data), fp); + + while (lenFile > 0){ + ::SendMessage(_hWnd, SCI_ADDTEXT, lenFile, (LPARAM) data); + lenFile = fread(data, 1, sizeof(data), fp); + } + + fclose(fp); + + }else{ + MsgBox.DisplayWarning("Can't load file %s", file->szFileName); + } + + ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 1, 0); + ::SendMessage(_hWnd, EM_EMPTYUNDOBUFFER, 0, 0); + ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0 , 0); + ::SendMessage(_hWnd, SCI_GOTOPOS, 0, 0); +} + +void GetFileType(CFileItem * file){ + if (!file) + return; + + if (file->nFileExtension){ + char * ext = file->szFileName + file->nFileExtension; + // H_FILE ? + if (!stricmp(ext, "h")){ + file->type = H_FILE; + return; + }else if (!stricmp(ext, "hpp")){ + file->type = H_FILE; + return; + }else if (!stricmp(ext, "hxx")){ + file->type = H_FILE; + return; + // C_FILE ? + }else if (!stricmp(ext, "c")){ + file->type = C_FILE; + return; + }else if (!stricmp(ext, "cpp")){ + file->type = C_FILE; + return; + }else if (!stricmp(ext, "cxx")){ + file->type = C_FILE; + return; + // RC_FILE ? + }else if (!stricmp(ext, "rc")){ + file->type = RC_FILE; + return; + } + } + file->type = U_FILE; +return; +} + +void CEditor::SaveFile(char * fullPath){ + if (!_hWnd) + return; + + FILE *fp = fopen(fullPath, "wb"); + if (fp){ + char data[blockSize + 1]; + int lengthDoc = ::SendMessage(_hWnd, SCI_GETLENGTH, 0, 0); + for (int i = 0; i < lengthDoc; i += blockSize) { + int grabSize = lengthDoc - i; + if (grabSize > blockSize) + grabSize = blockSize; + GetRange(i, i + grabSize, data); + fwrite(data, grabSize, 1, fp); + } + fclose(fp); + ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0, 0); + + }else{ + MsgBox.DisplayWarning("Can't save file %s", fullPath); + } +} + +int CEditor::GetCurrentPos(void){ + int currentPos = ::SendMessage(_hWnd, SCI_GETCURRENTPOS, 0,0); + caretPos = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, currentPos, 0) + 1; +return caretPos; +} + +void CEditor::GetRange(int start, int end, char *text){ + TextRange tr; + tr.chrg.cpMin = start; + tr.chrg.cpMax = end; + tr.lpstrText = text; + ::SendMessage(_hWnd, SCI_GETTEXTRANGE, 0, (LPARAM) &tr); +} + +void CEditor::SetAStyle(int style, COLORREF fore, COLORREF back, int size, const char *face){ + ::SendMessage(_hWnd, SCI_STYLESETFORE, style, fore); + ::SendMessage(_hWnd, SCI_STYLESETBACK, style, back); + if (size >= 1) + ::SendMessage(_hWnd, SCI_STYLESETSIZE, style, size); + if (face) + ::SendMessage(_hWnd, SCI_STYLESETFONT, style, (LPARAM) face); +} + +void CEditor::DefineMarker(int marker, int markerType, COLORREF fore, COLORREF back) { + ::SendMessage(_hWnd, SCI_MARKERDEFINE, marker, markerType); + ::SendMessage(_hWnd, SCI_MARKERSETFORE, marker, fore); + ::SendMessage(_hWnd, SCI_MARKERSETBACK, marker, back); +} + +void CEditor::SetLexer(int fileType){ + switch (fileType){ + + case H_FILE: + case C_FILE: + case RC_FILE: + SetCppLexer(); + return; + + default: + // Global default style. + SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana"); + ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles. + + } +} + +void CEditor::SetCppLexer(void){ + ::SendMessage(_hWnd, SCI_SETLEXER, SCLEX_CPP, 0); + ::SendMessage(_hWnd, SCI_SETSTYLEBITS, 5, 0); + + ::SendMessage(_hWnd, SCI_SETKEYWORDS, 0, (LPARAM) cppKeyWords); + + // Global default style. + SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana"); + ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles. + + // C Styles. + SetAStyle(SCE_C_DEFAULT, black, white, 10, "Verdana"); //0 + SetAStyle(SCE_C_COMMENT, Green, white, 0, 0); //1 + SetAStyle(SCE_C_COMMENTLINE, Green, white, 0, 0); //2 + SetAStyle(SCE_C_COMMENTDOC, darkGreen, white, 0, 0); //3 + SetAStyle(SCE_C_NUMBER, Ice, white, 0, 0); //4 + SetAStyle(SCE_C_WORD, darkBlue, white, 0, 0); //5 + ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_WORD, 1); + SetAStyle(SCE_C_STRING, Purple, white, 0, 0); //6 + SetAStyle(SCE_C_CHARACTER, Purple, white, 0, 0); //7 + SetAStyle(SCE_C_PREPROCESSOR, Olive, white, 0, 0); //9 + SetAStyle(SCE_C_OPERATOR, black, white, 0, 0); //10 + ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_OPERATOR, 1); +// SetAStyle(SCE_C_STRINGEOL, darkBlue, white, 0, 0); //12 +// SetAStyle(SCE_C_COMMENTLINEDOC, darkBlue, white, 0, 0); //15 +// SetAStyle(SCE_C_WORD2, darkBlue, white, 0, 0); //16 + ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold", (long)"1"); + ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.compact", (long)"1"); + ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.symbols", (long)"1"); + + ::SendMessage(_hWnd, SCI_SETFOLDFLAGS, 16, 0); + + // To put the folder markers in the line number region + //SendEditor(SCI_SETMARGINMASKN, 0, SC_MASK_FOLDERS); + + ::SendMessage(_hWnd, SCI_SETMODEVENTMASK, SC_MOD_CHANGEFOLD, 0); + + // Create a margin column for the folding symbols + ::SendMessage(_hWnd, SCI_SETMARGINTYPEN, 2, SC_MARGIN_SYMBOL); + + ::SendMessage(_hWnd, SCI_SETMARGINWIDTHN, 2, /*foldMargin ? foldMarginWidth :*/ 16); + + ::SendMessage(_hWnd, SCI_SETMARGINMASKN, 2, SC_MASK_FOLDERS); + ::SendMessage(_hWnd, SCI_SETMARGINSENSITIVEN, 2, 1); + + DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS, white, black); + DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS, white, black); + DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, white, black); + DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, white, black); + DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, white, black); + DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, white, black); + DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, white, black); + +return; +} + +void CEditor::GotoLine(int line, char * /*fileName*/){ + ::SendMessage(_hWnd, SCI_ENSUREVISIBLEENFORCEPOLICY, line, 0); + ::SendMessage(_hWnd, SCI_GOTOLINE, line, 0); +} + +bool CEditor::MarginClick(int position, int modifiers){ + int lineClick = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, position, 0); + //Platform::DebugPrintf("Margin click %d %d %x\n", position, lineClick, + // ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick) & SC_FOLDLEVELHEADERFLAG); +/* if ((modifiers & SCMOD_SHIFT) && (modifiers & SCMOD_CTRL)) { + FoldAll(); + } else {*/ + int levelClick = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick, 0); + if (levelClick & SC_FOLDLEVELHEADERFLAG) { + if (modifiers & SCMOD_SHIFT) { + // Ensure all children visible + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1); + Expand(lineClick, true, true, 100, levelClick); + } else if (modifiers & SCMOD_CTRL) { + if (::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, lineClick, 0)) { + // Contract this line and all children + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 0); + Expand(lineClick, false, true, 0, levelClick); + } else { + // Expand this line and all children + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1); + Expand(lineClick, true, true, 100, levelClick); + } + } else { + // Toggle this line + ::SendMessage(_hWnd, SCI_TOGGLEFOLD, lineClick, 0); + } + } +/* }*/ + return true; +} + +void CEditor::Expand(int &line, bool doExpand, bool force, int visLevels, int level){ + int lineMaxSubord = ::SendMessage(_hWnd, SCI_GETLASTCHILD, line, level & SC_FOLDLEVELNUMBERMASK); + line++; + while (line <= lineMaxSubord) { + if (force) { + if (visLevels > 0) + ::SendMessage(_hWnd, SCI_SHOWLINES, line, line); + else + ::SendMessage(_hWnd, SCI_HIDELINES, line, line); + } else { + if (doExpand) + ::SendMessage(_hWnd, SCI_SHOWLINES, line, line); + } + int levelLine = level; + if (levelLine == -1) + levelLine = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, line, 0); + if (levelLine & SC_FOLDLEVELHEADERFLAG) { + if (force) { + if (visLevels > 1) + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1); + else + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 0); + Expand(line, doExpand, force, visLevels - 1); + } else { + if (doExpand) { + if (!::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, line, 0)) + ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1); + Expand(line, true, force, visLevels - 1); + } else { + Expand(line, false, force, visLevels - 1); + } + } + } else { + line++; + } + } +} + diff --git a/rosapps/devutils/vmingw/editor.h b/rosapps/devutils/vmingw/editor.h new file mode 100644 index 00000000000..c098f871963 --- /dev/null +++ b/rosapps/devutils/vmingw/editor.h @@ -0,0 +1,165 @@ +/******************************************************************** +* Module: editor.h. This is part of Visual-MinGW. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +*******************************************************************/ +#ifndef EDITOR_H +#define EDITOR_H + +#include "Scintilla.h" +#include "SciLexer.h" +#include "winui.h" + +#define U_FILE 3 +#define H_FILE (U_FILE+1) +#define C_FILE (U_FILE+2) +#define RC_FILE (U_FILE+3) + +// Default block size. +const int blockSize = 131072; + +// Default colors. +const COLORREF black = RGB(0,0,0); +const COLORREF white = RGB(0xff,0xff,0xff); +const COLORREF darkBlue = RGB(0, 0, 0x7f); +const COLORREF Green = RGB(0, 0x7f, 0); +const COLORREF darkGreen = RGB(0x3f, 0x70, 0x3f); +const COLORREF Purple = RGB(0x7f, 0x00, 0x7f); +const COLORREF Ice = RGB(0x00, 0x7f, 0x7f); +const COLORREF Olive = RGB(0x7f, 0x7f, 0x00); + +// Default Cpp keywords. +const char cppKeyWords[] = +"asm auto bool break case catch char class const const_cast continue " +"default delete do double dynamic_cast else enum explicit export extern false float for " +"friend goto if inline int long mutable namespace new operator private protected public " +"register reinterpret_cast return short signed sizeof static static_cast struct switch " +"template this throw true try typedef typeid typename union unsigned using " +"virtual void volatile wchar_t while"; + +void EnsureRangeVisible(HWND hwndCtrl, int posStart, int posEnd, bool enforcePolicy); +int LengthDocument(HWND hwndCtrl); +CharacterRange GetSelection(HWND hwndCtrl); + +class CFileItem : public CNode +{ + public: + CFileItem(); + ~CFileItem(); + + // File name. + char szFileName[MAX_PATH]; + WORD nFileOffset; + WORD nFileExtension; + + // Owner tree view. + CTreeView * pTreeView; + HTREEITEM _hItem; + HTREEITEM _hDirItem; + + // Owner child window. + CMDIChild * pMdiChild; + int show; + bool isInProject; + + protected: + + private: +}; + +void GetFileType(CFileItem * file); + +class CEditor : public CScintilla +{ + public: + CEditor(); + ~CEditor(); + + void LoadFile(CFileItem * file); + void SaveFile(char * fullPath); + int GetCurrentPos(void); + void GotoLine(int line, char * fileName = NULL); + int caretPos; + void SetLexer(int fileType); + void SetCppLexer(void); + bool MarginClick(int position, int modifiers); + + protected: + + private: + void DefineMarker(int marker, int markerType, COLORREF fore, COLORREF back); + void GetRange(int start, int end, char *text); + void SetAStyle(int style, COLORREF fore, COLORREF back, int size, const char *face); + void Expand(int &line, bool doExpand, bool force = false, + int visLevels = 0, int level = -1); +}; + +#define FR_MAX_LEN 200 + +class CFindReplaceDlg : public CDlgBase +{ + public: + CFindReplaceDlg(); + virtual ~CFindReplaceDlg(); + + HWND Find(CScintilla * pEditor); + HWND Replace(CScintilla * pEditor); + + protected: + void FindNext(bool reverseDirection, bool showWarnings); + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL Find_OnInitDialog(void); + BOOL Replace_OnInitDialog(void); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + BOOL Find_OnCommand(WORD wIDl); + BOOL Replace_OnCommand(WORD wID); + BOOL HandleReplaceCommand(int cmd); + void ReplaceOnce(void); + void ReplaceAll(bool inSelection); + + private: + HWND hFindWhat; + HWND hReplaceWith; + HWND hWholeWord; + HWND hMatchCase; + HWND hRegExp; + HWND hWrap; + HWND hUnSlash; + HWND hUp; + HWND hDown; + char findWhat[FR_MAX_LEN + 1]; + char replaceWhat[FR_MAX_LEN + 1]; + + bool bWholeWord; + bool bMatchCase; + bool bRegExp; + bool bWrapFind; + bool bUnSlash; + bool bReverseFind; + bool bHavefound; + + CEditor * pEditor; + HWND hEditor; + int resId; +}; + +class CChooseFontDlg : public CWindow +{ + public: + CChooseFontDlg(); + ~CChooseFontDlg(); + + bool Create(CWindow * pWindow); + + protected: + CHOOSEFONT cf; + LOGFONT lf; + + private: +}; + +#endif diff --git a/rosapps/devutils/vmingw/license.htm b/rosapps/devutils/vmingw/license.htm new file mode 100644 index 00000000000..fefc521bf06 --- /dev/null +++ b/rosapps/devutils/vmingw/license.htm @@ -0,0 +1,121 @@ + + + +Visual-MinGW license agreement. + + + + + +
+ + + + + + + + + + + + +

Visual-MinGW's + license

+ + + +

  + + + + + + + + + + + + +

 

Visual-MinGW + is a C/C++ Integrated Development Environment.
+ Copyright (C) 2001  Manu B.

+

The following license + terms applies to Visual-MinGW:

+

This program is free software; + you can redistribute it and/or modify it + under the
terms of the GNU General Public + License version 2 as published by the Free +
+ Software Foundation.

+

This program is distributed + in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.
See + the
GNU + General Public License + for more details.

+

You should have received + a copy of the GNU General Public License
along with this program; + if not, write to the Free Software
Foundation, + Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307,USA.

+

 


 

Visual-MinGW + uses Neil Hodgson's + Scintilla + editing component as source + code
+ editor.

+

The + following license terms applies to both + Scintilla + and SciTE.

+

 

License + for Scintilla and SciTE

+ + + +
+ + + + +

 

+

 

Copyright + 1998-2001 by Neil Hodgson <neilh@scintilla.org>

+

All Rights Reserved

+

Permission to use, copy, + modify, and distribute this software and + its
documentation for any purpose and + without fee is hereby granted,
provided + that the above copyright notice appear in + all copies and that
both that copyright + notice and this permission notice appear + in
supporting documentation.

+

NEIL HODGSON DISCLAIMS + ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + OF MERCHANTABILITY
AND FITNESS, IN + NO EVENT SHALL NEIL HODGSON BE LIABLE FOR + ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING + FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER
TORTIOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE
OR + PERFORMANCE OF THIS SOFTWARE.

+

 

+

 

+

 

+ + + \ No newline at end of file diff --git a/rosapps/devutils/vmingw/license.txt b/rosapps/devutils/vmingw/license.txt new file mode 100644 index 00000000000..efd4e80ea66 --- /dev/null +++ b/rosapps/devutils/vmingw/license.txt @@ -0,0 +1,59 @@ +Visual-MinGW's license +---------------------- + +Visual-MinGW is a C/C++ Integrated Development Environment. +Copyright (C) 2001 Manu B. + +The following license terms applies to Visual-MinGW: + +This program is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License version 2 as published by the Free +Software Foundation. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. + +-------------------------------------------------------------------------------- + +Visual-MinGW uses Neil Hodgson's Scintilla editing component as source code +editor. + +The following license terms applies to both Scintilla and SciTE. + + +License for Scintilla and SciTE +------------------------------- + +Copyright 1998-2001 by Neil Hodgson + +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation. + +NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + + + + + + + + + diff --git a/rosapps/devutils/vmingw/main.cpp b/rosapps/devutils/vmingw/main.cpp new file mode 100644 index 00000000000..17f80dfd6c3 --- /dev/null +++ b/rosapps/devutils/vmingw/main.cpp @@ -0,0 +1,2622 @@ +/******************************************************************** +* Module: main.cpp. This is part of Visual-MinGW. +* +* Purpose: Main module. +* +* Authors: Manu B. +* +* License: Visual-MinGW is a C/C++ Integrated Development Environment. +* Copyright (C) 2001 Manu. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +* USA. +* +* (See license.htm for more details.) +* +* Revisions: +* Manu B. 12/15/01 CFileList created. +* +********************************************************************/ +#include +#include +#include +#include +#include "process.h" +#include "project.h" +#include "main.h" +#include "rsrc.h" + +#define MSG_MODIFIED "Modified" + +CCriticalSection CriticalSection; +extern CMessageBox MsgBox; +CFindReplaceDlg EditorDlg; +void Main_CmdTest(HWND hwnd); + +/* Globals */ +char * g_env_path = NULL; +char * g_vm_path = NULL; +CWinApp winApp; +CProject Project; +CChrono Chrono; + +// File filters & flags. +DWORD singleFileOpen = OFN_EXPLORER | OFN_FILEMUSTEXIST; +DWORD multipleFileOpen = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT; +DWORD fileSave = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | + OFN_OVERWRITEPROMPT; + +char * defFilter = "All Sources\0*.c;*.cpp;*.cxx;*.h;*.hpp;*.hxx;*.rc;*.mingw;*.prj\0" + "C Files\0*.c;*.cpp;*.cxx;*.rc\0" + "Headers\0*.h;*.hpp;*.hxx\0" + "Ini file\0*.ini\0" + "All Files (*.*)\0*.*\0\0"; + +char * prjFilter = "Project Files (*.prj)\0*.prj\0All Files (*.*)\0*.*\0\0"; +char * prjDefExt = "prj"; + +char * srcFilter = "All Sources\0*.c;*.cpp;*.cxx;*.h;*.hpp;*.hxx;*.rc\0" + "C Files\0*.c;*.cpp;*.cxx;*.rc\0" + "Headers\0*.h;*.hpp;*.hxx\0" + "All Files (*.*)\0*.*\0\0"; +char * srcDefExt = "cpp"; + +/* For tests */ + CChooseFontDlg CChooseFont; +void Main_CmdTest(HWND){ + winApp.Process.AddTask( + "sh.exe", + IN_PIPE || OUTERR_PIPE, + LVOUT_ERROR); + winApp.Process.Run(); +/* CChooseFont.Create(&winApp);*/ +return; +} + + +/******************************************************************** +* Class: CFileDlg. +* +* Purpose: A CFileDlgBase for Open/Save dlg boxes. +* +* Revisions: +* +********************************************************************/ +CFileDlg::CFileDlg(){ +} + +CFileDlg::~CFileDlg(){ +} + +bool CFileDlg::Open(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag){ + + switch(fileflag){ + // Project file. + case PRJ_FILE: + SetData(prjFilter, prjDefExt, singleFileOpen); + break; + + // Add multiple files to project. + case ADD_SRC_FILE: + Reset(); + SetTitle("Add files to project"); + nMaxFile = 2048; + SetFilterIndex(1); + SetData(srcFilter, srcDefExt, multipleFileOpen); + break; + + default: // SRC_FILE + SetData(defFilter, srcDefExt, singleFileOpen); + SetFilterIndex(1); + break; + } +return OpenFileName(pWindow, pszFileName, nMaxFile); +} + +bool CFileDlg::Save(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag){ + Reset(); + + switch(fileflag){ + case SRC_FILE: + SetData(defFilter, srcDefExt, fileSave); + SetFilterIndex(1); + break; + + default: // PRJ_FILE + SetData(prjFilter, prjDefExt, fileSave); + break; + } +return SaveFileName(pWindow, pszFileName, nMaxFile); +} + + +/******************************************************************** +* Class: CPreferencesDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CPreferencesDlg::CPreferencesDlg(){ +} + +CPreferencesDlg::~CPreferencesDlg(){ +} + +int CPreferencesDlg::Create(void){ +return CreateModal(&winApp, IDD_PREFERENCES, (LPARAM) this); +} + +LRESULT CALLBACK CPreferencesDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_NOTIFY: + OnNotify((int) wParam, (LPNMHDR) lParam); + break; + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CPreferencesDlg::OnInitDialog(HWND, LPARAM){ + // Tab control handle and TCITEM. + _hWndTab = ::GetDlgItem(_hWnd, IDC_PREF_TABS); + tcitem.mask = TCIF_TEXT | TCIF_PARAM; + + // Insert tabs. + HWND hwndChild = EnvDlg.Create(this, IDD_ENVIRON, NULL, (long) NULL); + tcitem.pszText = "Environment"; + tcitem.lParam = (long) &EnvDlg; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 0, (LPARAM)&tcitem); + SetChildPosition(hwndChild); + +/* tcitem.pszText = "General"; + tcitem.lParam = (long) NULL; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 1, (LPARAM)&tcitem); + + tcitem.pszText = "Find in files"; + tcitem.lParam = (long) NULL; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 2, (LPARAM)&tcitem);*/ + + // Show the dialog and default pane. + Show(); + EnvDlg.Show(); + EnvDlg.SetFocus(); +return TRUE; +} + +BOOL CPreferencesDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + EnvDlg.OnCommand(0, wID, 0); + EndDlg(IDOK); + return TRUE; + + case IDCANCEL: + EndDlg(IDCANCEL); + return FALSE; + + case IDAPPLY: + EnvDlg.OnCommand(0, wID, 0); + return TRUE; + } +return FALSE; +} + +BOOL CPreferencesDlg::EndDlg(int nResult){ + EnvDlg.EndDlg(0); + EnvDlg.bIsVisible = false; + if (_hWnd){ + BOOL result = ::EndDialog(_hWnd, nResult); + _hWnd = 0; + return result; + } +return false; +} + + +/******************************************************************** +* Class: CEnvDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CEnvDlg::CEnvDlg(){ +} + +CEnvDlg::~CEnvDlg(){ +} + +LRESULT CALLBACK CEnvDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + } +return FALSE; +} + +BOOL CEnvDlg::OnInitDialog(HWND, LPARAM){ + bIsVisible = false; + bModified = false; + /* Get control handles */ + hApply = ::GetDlgItem(_pParent->_hWnd, IDAPPLY); + hSetCcBin = GetItem(IDC_SET_CCBIN); + hCcBinDir = GetItem(IDC_CCBIN); + hBrowseCc = GetItem(IDC_BROWSE_CC); + hSetCmdBin = GetItem(IDC_SET_CMDBIN); + hCmdBinDir = GetItem(IDC_CMDBIN); + hBrowseCmd = GetItem(IDC_BROWSE_CMD); + hAutoexec = GetItem(IDC_AUTOEXEC); + hEnvView = GetItem(IDC_ENV_VIEW); + + if (winApp.bSetCcEnv) + ::SendMessage(hSetCcBin, BM_SETCHECK, BST_CHECKED, 0); + if (winApp.bSetCmdEnv) + ::SendMessage(hSetCmdBin, BM_SETCHECK, BST_CHECKED, 0); + if (winApp.bSetDefEnv) + ::SendMessage(hAutoexec, BM_SETCHECK, BST_CHECKED, 0); + + SetItemText(hCcBinDir, winApp.szCcBinDir); + SetItemText(hCmdBinDir, winApp.szCmdBinDir); + SetEnvText(); +/* hCcIncDir = GetItem(IDC_CC_INCDIR); + + SetItemText(hCcIncDir, winApp.includeDir);*/ + bIsVisible = true; +return TRUE; +} + +BOOL CEnvDlg::OnCommand(WORD wNotifyCode, WORD wID, HWND){ + char directory[MAX_PATH]; + + switch (wID){ + case IDC_BROWSE_CC: + if (winApp.ShellDlg.BrowseForFolder(&winApp, directory, "Browse", + BIF_RETURNONLYFSDIRS)){ + SetItemText(hCcBinDir, directory); + } + return TRUE; + + case IDC_BROWSE_CMD: + if (winApp.ShellDlg.BrowseForFolder(&winApp, directory, "Browse", + BIF_RETURNONLYFSDIRS)){ + SetItemText(hCmdBinDir, directory); + } + return TRUE; + + case IDOK: + winApp.bSetCcEnv = + (BST_CHECKED==::SendMessage(hSetCcBin, BM_GETCHECK, 0, 0)); + winApp.bSetCmdEnv = + (BST_CHECKED==::SendMessage(hSetCmdBin, BM_GETCHECK, 0, 0)); + winApp.bSetDefEnv = + (BST_CHECKED==::SendMessage(hAutoexec, BM_GETCHECK, 0, 0)); + + GetItemText(hCcBinDir, winApp.szCcBinDir, MAX_PATH); + GetItemText(hCmdBinDir, winApp.szCmdBinDir, MAX_PATH); +// GetItemText(hCcIncDir, winApp.includeDir, MAX_PATH); + if (bModified) + winApp.SetEnv(); + return TRUE; + + case IDCANCEL: + return FALSE; + + case IDAPPLY: + if (bModified){ + winApp.bSetCcEnv = + (BST_CHECKED==::SendMessage(hSetCcBin, BM_GETCHECK, 0, 0)); + winApp.bSetCmdEnv = + (BST_CHECKED==::SendMessage(hSetCmdBin, BM_GETCHECK, 0, 0)); + winApp.bSetDefEnv = + (BST_CHECKED==::SendMessage(hAutoexec, BM_GETCHECK, 0, 0)); + + GetItemText(hCcBinDir, winApp.szCcBinDir, MAX_PATH); + GetItemText(hCmdBinDir, winApp.szCmdBinDir, MAX_PATH); + winApp.SetEnv(); + SetEnvText(); + bModified = false; + ::EnableWindow(hApply, false); + } + return TRUE; + + default: + if (bIsVisible && !bModified){ + switch(wNotifyCode){ + case EN_CHANGE: + case BN_CLICKED: + bModified = true; + ::EnableWindow(hApply, true); + return TRUE; + } + } + break; + } +return FALSE; +} + +void CEnvDlg::SetEnvText(void){ + if (g_vm_path){ + char * text = (char *) malloc(strlen(g_vm_path)+20); // 10 lines max. + char * start = text; + char * parse = g_vm_path; + while (*parse){ + if (*parse == ';'){ + // Change ';' into CR/LF. + *text = '\r'; + text++; + *text = '\n'; + text++; + parse++; + }else if (*parse == '='){ + // Rewind buffer. + text = start; + parse++; + }else{ + // Copy one char. + *text = *parse; + text++; + parse++; + } + } + *text = '\0'; + SetItemText(hEnvView, start); + free(start); + } +} + + +/******************************************************************** +* Class: CGrepDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CGrepDlg::CGrepDlg(){ + *findWhat = '\0'; + *gDir = '\0'; +} + +CGrepDlg::~CGrepDlg(){ +} + +int CGrepDlg::Create(void){ +return CreateModal(&winApp, IDD_GREP, (LPARAM) this); +} + +LRESULT CALLBACK CGrepDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CGrepDlg::OnInitDialog(HWND, LPARAM){ + hFindWhat = GetItem(IDC_FINDWHAT); + hgDir = GetItem(IDC_GFILTER); + + SetItemText(hFindWhat, findWhat); + SetItemText(hgDir, gDir); + // Show the dialog and default pane. + Show(); +return TRUE; +} + +BOOL CGrepDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + GetItemText(hFindWhat, findWhat, sizeof(findWhat)); + GetItemText(hgDir, gDir, sizeof(gDir)); + FindInFiles(findWhat, gDir); + return TRUE; + + case IDCANCEL: + EndDlg(IDCANCEL); + return FALSE; + } +return FALSE; +} + +void CGrepDlg::FindInFiles(char * findWhat, char * fileFilter){ + if (!findWhat || !fileFilter || winApp.Process.isRunning()) + return; + + winApp.Report.Clear(); + winApp.Report.Append("Grep search...", LVOUT_NORMAL); + + winApp.Process.AddTask("grep -G -n -H ", OUTERR_PIPE, LVOUT_ERROR); + winApp.Process.CmdCat(findWhat); + winApp.Process.CmdCat(" "); + winApp.Process.CmdCat(fileFilter); + + winApp.Process.Run(); +} + + +/******************************************************************** +* Functions: WinMain procedure. +* +* Purpose: Runs the application. +* +* Revisions: +* +********************************************************************/ +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ +return winApp.Run(hInstance, hPrevInstance, lpCmdLine, nCmdShow); +} + + +/******************************************************************** +* Class: CWinApp. +* +* Purpose: Manages the all application. +* +* Revisions: +* +********************************************************************/ +CWinApp::CWinApp(){ + *iniFileName = '\0'; + hmod = NULL; + *openFilesDir ='\0'; + *projectDir = '\0'; + *includeDir = '\0'; + bSetCcEnv = false; + bSetCmdEnv = false; + bSetDefEnv = false; + *szCcBinDir = '\0'; + *szCmdBinDir = '\0'; + + firstRun = false; + // Child windows dimensions. + deltaY = 0; + tbarHeight = 26; + sbarHeight = 20; + tvWidth = 140; + lvHeight = 120; + + hSplitter = 4; + vSplitter = 4; +} + +CWinApp::~CWinApp(){ +} + +bool CWinApp::CustomInit(void){ + /* Get PATH environment variable */ + char * env_path = getenv("PATH"); + if (env_path) + g_env_path = strdup(env_path); + + SetName("Visual MinGW", APP_VERSION); + MsgBox.SetCaption("Visual MinGW"); + IsWinNT(); + ReadIniFile("visual-mingw.ini"); + + hAccel = LoadAccelerators(_hInst, "ACCELS"); + hmod = LoadLibrary("SciLexer.DLL"); + if (!hmod){ + MsgBox.DisplayFatal("Unable to load SciLexer.DLL"); + return false; + } +return true; +} + +bool CWinApp::Release(void){ + WriteIniFile(); + if (hmod) + FreeLibrary(hmod); + if (g_env_path) + free(g_env_path); +return true; +} + +bool CWinApp::ReadIniFile(char * fileName){ + ParseCmdLine(iniFileName); + strcat(iniFileName, fileName); + + if (!IniFile.Load(iniFileName)){ + /* Create an empty file and fill it */ + firstRun = true; + MsgBox.DisplayWarning("Visual-MinGW first run !\n" + "Step 1: User interface initialization.\n" + "Please report bugs to Visual-MinGW home page.\n" + "See the Readme text for more information."); + FILE * file = fopen(iniFileName, "wb"); + if (!file) + return false; + SaveIniFile(file); + fclose(file); + return false; + } + // [General] section + IniFile.GetString(openFilesDir, "FilesDirectory", "General" ); + IniFile.GetString(projectDir, "ProjectDirectory" ); + bSetDefEnv = IniFile.GetInt( "SetDefEnv" ); + bSetCmdEnv = IniFile.GetInt( "SetBinDir" ); + IniFile.GetString(szCmdBinDir, "BinDir" ); + // [Compiler] section + IniFile.GetString(includeDir, "IncludeDir", "Compiler" ); + bSetCcEnv = IniFile.GetInt( "SetBinDir" ); + IniFile.GetString(szCcBinDir, "BinDir" ); + + SetEnv(); +return true; +} + +void CWinApp::SaveIniFile(FILE * file){ + // [General] + fprintf (file, "\t; Generated automatically by Visual-MinGW.\n"); + fprintf (file, "\t ; http://visual-mingw.sourceforge.net/\n"); + fprintf (file, "[General]\nSignature = 40"); + fprintf (file, "\nFilesDirectory = %s", openFilesDir); + fprintf (file, "\nProjectDirectory = %s", projectDir); + fprintf (file, "\nTvWidth = %d", tvWidth); + fprintf (file, "\nLvHeight = %d", lvHeight); + fprintf (file, "\nSetDefEnv = %d", bSetDefEnv); + fprintf (file, "\nSetBinDir = %d", bSetCmdEnv); + fprintf (file, "\nBinDir = %s", szCmdBinDir); + // [Compiler] + fprintf (file, "\n\n[Compiler]\nIncludeDir = %s", includeDir); + fprintf (file, "\nSetBinDir = %d", bSetCcEnv); + fprintf (file, "\nBinDir = %s", szCcBinDir); +} + +bool CWinApp::WriteIniFile(void){ + if (*iniFileName == '\0') + return false; + FILE * file = fopen(iniFileName, "wb"); + if (!file) + return false; + SaveIniFile(file); + fclose(file); + IniFile.Close(); +return true; +} + +bool CWinApp::SetEnv(void){ + // Free previous variable. + //getenv("PATH="); + // Malloc a buffer. + int len = 0; + if (bSetCcEnv) + len += strlen(winApp.szCcBinDir); + if (bSetCmdEnv) + len += strlen(winApp.szCmdBinDir); + if (bSetDefEnv && g_env_path) + len += strlen(g_env_path); + g_vm_path = (char *) malloc(len+8); + + // Copy the environment variable. + strcpy(g_vm_path, "PATH="); + if (bSetCcEnv && *winApp.szCcBinDir){ + strcat(g_vm_path, winApp.szCcBinDir); + strcat(g_vm_path, ";"); + } + if (bSetCmdEnv && *winApp.szCmdBinDir){ + strcat(g_vm_path, winApp.szCmdBinDir); + strcat(g_vm_path, ";"); + } + if (bSetDefEnv && g_env_path) + strcat(g_vm_path, g_env_path); + + len = strlen(g_vm_path) - 1; + if (g_vm_path[len] == ';') + g_vm_path[len] = '\0'; + if (putenv(g_vm_path) == -1){ + free(g_vm_path); + g_vm_path = NULL; + return false; + } +return true; +} + + +/******************************************************************** +* CWinApp: Create each application's window. +********************************************************************/ +bool CWinApp::CreateUI(void){ + + InitCommonControls(); + + // Custom values. + wc.style = 0; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = NULL; + wc.hbrBackground = //NULL; + (HBRUSH)(COLOR_INACTIVEBORDER + 1); + wc.lpszMenuName = MAKEINTRESOURCE(ID_MENU); + wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + if(!MainRegisterEx("main_class")) { + MsgBox.DisplayFatal("Can't Register Main Window"); + return false; + } + + // Custom values. + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + + if(!ChildRegisterEx("child_class")) { + MsgBox.DisplayFatal("Can't Register MDI Class"); + return false; + } + + // Use a CreateWindowEx like procedure. + HWND hwnd = CreateEx( + this, // Owner class. + 0, + mainClass, + appName, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + NULL); + + if(!hwnd) { + MsgBox.DisplayFatal("Can't create Main window"); + return false; + } + MsgBox.SetParent(hwnd); + + // SW_SHOWMAXIMIZED. + ::ShowWindow(hwnd, SW_SHOWMAXIMIZED); + ::UpdateWindow(hwnd); + if (firstRun) + FirstRunTest(); + firstRun = false; +return true; +} + +void CWinApp::FirstRunTest(void){ + MsgBox.DisplayWarning("Visual-MinGW first run !\n" + "Step 2: You will now set your environment variables.\n" + "\"Use default environment variables\" should be checked.\n" + "Then Visual-MinGW will try to launch the compiler."); + PreferencesDlg.Create(); + MsgBox.DisplayWarning("Visual-MinGW first run !\n" + "Step 3: Installation checking.\n" + "Try to launch rm and gcc.\n" + "See \"Main\" or \"Log\" report views for results.\n"); + winApp.Report.Clear(); + winApp.Report.Append("Testing for first run...", LVOUT_NORMAL); + + // Put the command line and the run flag in the command stack. + winApp.Process.AddTask("gcc -v", OUTERR_PIPE, LVOUT_NORMAL); + winApp.Process.AddTask("rm --version", OUTERR_PIPE, LVOUT_NORMAL); + winApp.Process.Run(); +return; +} + +void CWinApp::CreateToolbar(void){ + Toolbar.CreateEx( + this, + 0, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + |TBSTYLE_FLAT | TBSTYLE_TOOLTIPS + | CCS_NORESIZE); + + Toolbar.AddBitmap(IDB_TOOLBAR, 15); + + TBBUTTON tbButtons [] = + { { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0}, + { 0, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 1, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 2, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0}, + { 3, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 4, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 5, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0}, + { 6, IDM_UNDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0}, + { 7, IDM_REDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0} }; + + int numbutton = sizeof tbButtons/sizeof tbButtons[0]; + + Toolbar.AddButtons(&tbButtons[0], numbutton); +} + +void CWinApp::CreateSplitter(void){ + MainSplitter.Init(&ChildSplitter, &Report, SPLSTYLE_HORZ, lvHeight, SPLMODE_2); + ChildSplitter.Init(&Manager, &MdiClient, SPLSTYLE_VERT, tvWidth, SPLMODE_1); + + // File Manager. + Manager.Create(this); + // MDI client. + CreateMDI(); + // ListView. + Report.Create(this); +} + +void CWinApp::CreateMDI(void){ + MdiClient.Init(3, ID_FIRSTCHILD); + MdiClient.CreateEx( + this, + WS_EX_CLIENTEDGE, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | WS_VSCROLL | WS_HSCROLL + ); +} + +HWND CWinApp::CreateChild(char * caption, LPVOID lParam){ + + CChildView * mdiChild = new CChildView; + + HWND hwnd = mdiChild->CreateEx( + &MdiClient, // MUST be an MdiClient *. + WS_EX_MDICHILD, + MDIS_ALLCHILDSTYLES | WS_CHILD | WS_SYSMENU | WS_CAPTION + | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX + | WS_MAXIMIZE, + caption, + 0, + lParam); + + if (!hwnd) + delete mdiChild; +return hwnd; +} + +void CWinApp::CreateStatusBar(void){ + Sbar.CreateEx( + this, + 0, + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBARS_SIZEGRIP); + + int sbWidths[] = {60, 120, -1}; + + int numparts = sizeof sbWidths/sizeof sbWidths[0]; + + Sbar.SetParts(numparts, &sbWidths[0]); +} + +void CWinApp::SendCaretPos(int caretPos) { + // To display the "Line : xxxx" message, we use our standard msgBuf[256]. + sprintf(msgBuf, "Line : %d", caretPos); + Sbar.SendMessage(SB_SETTEXT, 0, (LPARAM) msgBuf); +return; +} + + +/******************************************************************** +* CWinApp: Message handling procedures. +********************************************************************/ +LRESULT CALLBACK CWinApp::CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_CREATE: + return OnCreate((LPCREATESTRUCT) lParam); + + case WM_PAINT: + return OnPaint((HDC) wParam); + + case WM_SIZE: + return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + + case WM_DESTROY: + return OnDestroy(); + + case WM_COMMAND: + return OnCommand(wParam, lParam); + + case WM_CLOSE: + return OnClose(); + + case WM_NOTIFY: + return OnNotify((int) wParam, (LPNMHDR) lParam); + + case WM_LBUTTONDOWN: + return OnLButtonDown((short) LOWORD(lParam), (short) HIWORD(lParam), wParam); + + case WM_MOUSEMOVE: + return OnMouseMove((short) LOWORD(lParam), (short) HIWORD(lParam), wParam); + + case WM_LBUTTONUP: + return OnLButtonUp((short) LOWORD(lParam), (short) HIWORD(lParam), wParam); + + case WM_SETCURSOR: + OnSetCursor((HWND) wParam, (UINT) LOWORD(lParam), (UINT) HIWORD(lParam)); + return DefWindowProc(_hWnd, Message, wParam, lParam); + + default: + return DefFrameProc(_hWnd, MdiClient.GetId(), Message, wParam, lParam); + } +return 0; +} + +BOOL CWinApp::OnCreate(LPCREATESTRUCT){ + // Toolbar. + CreateToolbar(); + // Splitter. + CreateSplitter(); + // Statusbar. + CreateStatusBar(); +return TRUE; +} + +BOOL CWinApp::OnPaint(HDC){ + PAINTSTRUCT ps; + BeginPaint(_hWnd, &ps); + EndPaint(_hWnd, &ps); +return 0; +} + +BOOL CWinApp::OnSize(UINT, int width, int height){ + // TreeView and MDI Client delta-height. + deltaY = height-sbarHeight-lvHeight-vSplitter-tbarHeight; + + if (deltaY>3){ + Toolbar.SetPosition(0, + 0, 0, + width, tbarHeight, + 0); + + MainSplitter.SetPosition(0, + 0, tbarHeight, + width, height-tbarHeight-sbarHeight, + 0); + + Sbar.SetPosition(0, + 0, height-sbarHeight, + width, sbarHeight, + 0); + } + InvalidateRect(_hWnd, NULL, false); +return 0; +} + +BOOL CWinApp::OnDestroy(void){ + PostQuitMessage(0); +return 0; +} + +BOOL CWinApp::OnClose(void){ + if (IDCANCEL == Manager.SaveAll(IDASK)) // Ask to save. + return TRUE; // Cancelled by user. + ::DestroyWindow(_hWnd); +return 0; +} + +BOOL CWinApp::OnNotify(int idCtrl, LPNMHDR notify){ + Manager.OnNotify(idCtrl, notify); + Report.OnNotify(idCtrl, notify); +return 0; +} + +BOOL CWinApp::OnLButtonDown(short xPos, short yPos, UINT){ + MainSplitter.OnLButtonDown(_hWnd, xPos, yPos); + ChildSplitter.OnLButtonDown(_hWnd, xPos, yPos); +return 0; +} + +BOOL CWinApp::OnMouseMove(short xPos, short yPos, UINT){ + MainSplitter.OnMouseMove(_hWnd, xPos, yPos); + ChildSplitter.OnMouseMove(_hWnd, xPos, yPos); +return 0; +} + +BOOL CWinApp::OnLButtonUp(short xPos, short yPos, UINT){ + MainSplitter.OnLButtonUp(_hWnd, xPos, yPos); + ChildSplitter.OnLButtonUp(_hWnd, xPos, yPos); +return 0; +} + +BOOL CWinApp::OnSetCursor(HWND, UINT nHittest, UINT){ + if (nHittest == HTCLIENT) { + if (MainSplitter.OnSetCursor(_hWnd, 0)){ + return 0; + }else if (ChildSplitter.OnSetCursor(_hWnd, 0)){ + return 0; + }else{ + ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); + } + } +return 0; +} + + +/******************************************************************** +* CWinApp: Dispatch command messages. +********************************************************************/ +BOOL CWinApp::OnCommand(WPARAM wParam, LPARAM lParam){ + int wID = LOWORD(wParam); + + switch (wID){ + /* File Menu */ + case IDM_NEW: + Manager.FilesView.New(); + break; + + case IDM_OPEN: + Manager.OpenFileDialog(); + break; + + case IDM_NEW_PROJECT: + Manager.NewProjectDialog(); + break; + + case IDM_OPEN_PROJECT: + Manager.OpenProjectDialog(); + break; + + case IDM_SAVE_PROJECT: + Manager.SaveProjectFiles(IDYES); + break; + + case IDM_CLOSE_PROJECT: + Manager.CloseProject(); + break; + + case IDM_PREFERENCES: + PreferencesDlg.Create(); + break; + + case IDM_QUIT: + PostMessage(_hWnd, WM_CLOSE, 0, 0); + break; + + /* Find Menu */ + case IDM_GREP: + GrepDlg.Create(); + break; + + /* Window Menu */ + case IDM_CASCADE: + PostMessage(MdiClient.GetId(), WM_MDICASCADE, 0, 0); + break; + case IDM_TILEHORZ: + PostMessage(MdiClient.GetId(), WM_MDITILE, MDITILE_HORIZONTAL, 0); + break; + case IDM_TILEVERT: + PostMessage(MdiClient.GetId(), WM_MDITILE, MDITILE_VERTICAL, 0); + break; + case IDM_ARRANGE: + PostMessage(MdiClient.GetId(), WM_MDIICONARRANGE, 0, 0); + break; + + /* Project Menu */ + case IDM_NEW_MODULE: + Project.NewModuleDlg(); + break; + + case IDM_ADD: + Project.AddFiles(); + break; + + case IDM_REMOVE_FILE: + Manager.RemoveProjectFile(); + break; + + case IDM_REMOVE_MODULE: + Manager.RemoveProjectModule(); + break; + + case IDM_OPTION: + Project.OptionsDlg(); + break; + + case IDM_ZIP_SRCS: + Project.ZipSrcs(); + break; + + case IDM_EXPLORE: + Project.Explore(_hWnd); + break; + + /* Build Menu */ + case IDM_BUILD: + Project.Build(); + break; + + case IDM_REBUILDALL: + Project.RebuildAll(); + break; + + case IDM_RUN_TARGET: + Project.RunTarget(); + break; + + case IDM_MKCLEAN: + Project.MakeClean(); + break; + + case IDM_MKF_BUILD: + Project.BuildMakefile(); + break; + + case IDM_RUN_CMD: + winApp.Process.CommandDlg.Create(); + break; + + case IDM_TEST: + Main_CmdTest(_hWnd); + break; + + default:{ + if (wID >= ID_FIRSTCHILD){ + DefFrameProc(_hWnd, MdiClient.GetId(), WM_COMMAND, wParam, lParam); + }else{ + HWND hChildWindow = (HWND) MdiClient.SendMessage(WM_MDIGETACTIVE); + + if (hChildWindow) + ::SendMessage(hChildWindow, WM_COMMAND, wParam, lParam); + } + } + } +return TRUE; +} + + +/******************************************************************** +* CWinApp: Handles child messages. +********************************************************************/ +LRESULT CALLBACK CWinApp::CChildWndProc(CWindow * pWnd, UINT Message, WPARAM wParam, LPARAM lParam){ + + CChildView * childView = (CChildView *) pWnd; + HWND hwndChild = childView->_hWnd; + + switch(Message){ + case WM_CREATE: + childView->OnCreate((LPCREATESTRUCT) lParam); + break; + + case WM_SIZE: + childView->OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + break; + + case WM_COMMAND: + childView->OnCommand(wParam, lParam); + break; + + case WM_DESTROY: + childView->OnDestroy(); + break; + + case WM_CLOSE: + if (childView->OnClose()){ + MdiClient.SendMessage(WM_MDIDESTROY,(WPARAM) hwndChild, 0); + } + return true; + + case WM_NOTIFY: + childView->OnNotify((int) wParam, (LPNMHDR) lParam); + break; + + case WM_SETFOCUS: + childView->OnSetFocus((HWND) wParam); + break; + + case WM_MDIACTIVATE: + childView->OnActivate((HWND) wParam, (HWND) lParam); + break; + } +return DefMDIChildProc(hwndChild, Message, wParam, lParam); +} + + +/******************************************************************** +* Class: CChildView. +* +* Purpose: MDI child window class. +* +* Revisions: +* +********************************************************************/ +CChildView::CChildView(){ + modified = false; +} + +CChildView::~CChildView(){ +} + +bool CChildView::OnCreate(LPCREATESTRUCT){ + CFileItem * file = (CFileItem *) GetLong(GWL_USERDATA); + + // Create Scintilla Editor Control. + HWND hwnd = Editor.CreateEx( + this, + 0, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | WS_VSCROLL | WS_HSCROLL); + + if (!hwnd) + return false; // @@TODO need to manage creation failure. + + // Set window handles + file->pMdiChild = this; + + // Load a file if there is one to load. + Editor.LoadFile(file); +return true; +} + +bool CChildView::OnSize(UINT wParam, int width, int height){ + if(wParam != SIZE_MINIMIZED){ + Editor.SetPosition(0, + 0, + 0, + width, + height, + 0); + } +return true; +} + +BOOL CChildView::OnClose(void){ + if (modified){ + int decision = MsgBox.AskToSave(true); + switch (decision){ + case IDCANCEL: + return FALSE; + + case IDYES: + CmdSave(); + break; + } + } +return TRUE; +} + +BOOL CChildView::OnDestroy(void){ + CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA); + + if (file){ + if (!file->isInProject){ + // A simple file. + winApp.Manager.FilesView.CloseFile(file); + }else{ + // A project one. + file->pMdiChild = NULL; + //modified = false; + } + } +return 0; +} + +BOOL CChildView::OnNotify(int, LPNMHDR notify){ + SCNotification * notification = (SCNotification *) notify; + + // Notify Message from Current Editor Control. + if (notify->hwndFrom == Editor._hWnd){ + switch (notify->code){ + case SCN_UPDATEUI: + Editor.GetCurrentPos(); + winApp.SendCaretPos(Editor.caretPos); + break; + + case SCN_SAVEPOINTREACHED: + modified = false; + winApp.Sbar.WriteString("", 1); + break; + + case SCN_SAVEPOINTLEFT: + modified = true; + winApp.Sbar.WriteString(MSG_MODIFIED, 1); + break; + + case SCN_MARGINCLICK: + if (notification->margin == 2) + Editor.MarginClick(notification->position, notification->modifiers); + break; + } + } +return 0; +} + +BOOL CChildView::OnSetFocus(HWND){ + CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA); + if (!file) + return false; + // Select corresponding TreeView item. + CTreeView * pTreeView = file->pTreeView; + + if(!pTreeView) + return false; + + pTreeView->SendMessage(TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)file->_hItem); + + // Set Focus on Editor Control. + Editor.SetFocus(); + + // Display "Modified" message or nothing in the Status Bar. + winApp.SendCaretPos(Editor.caretPos); + + if(modified) + winApp.Sbar.SendMessage(SB_SETTEXT, 1, (LPARAM) MSG_MODIFIED); + else + winApp.Sbar.SendMessage(SB_SETTEXT, 1, (LPARAM) ""); + + int selectedTab = winApp.Manager.SendMessage(TCM_GETCURSEL); + + if (file->isInProject == true && selectedTab != PROJECT_TAB){ + winApp.Manager.SendMessage(TCM_SETCURFOCUS, PROJECT_TAB); + }else if (file->isInProject == false && selectedTab != FILES_TAB){ + winApp.Manager.SendMessage(TCM_SETCURFOCUS, FILES_TAB); + } +return 0; +} + +BOOL CChildView::OnActivate(HWND, HWND hwndChildAct){ + HMENU hMenu; + HMENU hFileMenu; + BOOL EnableFlag; + HWND hwndMain = winApp._hWnd; + + hMenu = GetMenu(hwndMain); + + if(_hWnd == hwndChildAct){ + EnableFlag = TRUE; //being activated + }else{ + EnableFlag = FALSE; //being de-activated + } + // Menu items. + EnableMenuItem(hMenu, 1, MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(hMenu, 3, MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + + // Sub-menu items. + hFileMenu = GetSubMenu(hMenu, 0); + EnableMenuItem(hFileMenu, IDM_SAVE, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(hFileMenu, IDM_SAVEAS, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + hFileMenu = GetSubMenu(hMenu, 2); + EnableMenuItem(hFileMenu, IDM_FIND, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(hFileMenu, IDM_REPLACE, MF_BYCOMMAND | (EnableFlag ? MF_ENABLED : MF_GRAYED)); + DrawMenuBar(hwndMain); +return 0; +} + +void CChildView::CmdSave(void){ + CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA); + + if (!file) + return; + /* Untitled file ? */ + if (file->nFileOffset == 0){ + CmdSaveAs(); + return; + } + + if (!file->isInProject){ + // A simple file. + Editor.SaveFile(file->szFileName); + }else{ + // A project one. + Project.szDirBuffer[Project.nFileOffset - 1] = '\\'; + strcpy(&Project.szDirBuffer[Project.nFileOffset], file->szFileName); + Editor.SaveFile(Project.szDirBuffer); + Project.szDirBuffer[Project.nFileOffset - 1] = '\0'; + } +} + +void CChildView::CmdSaveAs(void){ + CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA); + if (!file) + return; + + char fileName[MAX_PATH]; + if (!winApp.FileDlg.Save(&winApp, fileName, MAX_PATH, SRC_FILE)) //@@ + return; // canceled by user + + ::SetWindowText(_hWnd, fileName); + strcpy(file->szFileName, fileName); + + Editor.SaveFile(file->szFileName); + //@@ TODO we need to check for errors +} + +BOOL CChildView::OnCommand(WPARAM wParam, LPARAM){ + CFileItem * file = (CFileItem*) GetLong(GWL_USERDATA); + + if(!file) + return false; + + switch (LOWORD(wParam)){ + case IDM_SAVE: + CmdSave(); + break; + + case IDM_SAVEAS: + CmdSaveAs(); + break; + + case IDM_SAVEALL: + winApp.Manager.SaveAll(IDYES); // Silent. + break; + +/* case IDM_CLOSE: + PostMessage(pWnd, WM_CLOSE, 0, 0); + break; +*/ + // To Scintilla control. + case IDM_FIND: + EditorDlg.Find(&Editor); + break; + + case IDM_REPLACE: + EditorDlg.Replace(&Editor); + break; + + case IDM_CUT: + Editor.SendMessage(SCI_CUT); + break; + case IDM_COPY: + Editor.SendMessage(SCI_COPY); + break; + case IDM_PASTE: + Editor.SendMessage(SCI_PASTE); + break; + case IDM_UNDO: + Editor.SendMessage(SCI_UNDO); + break; + case IDM_REDO: + Editor.SendMessage(SCI_REDO); + break; + case IDM_SELECTALL: + Editor.SendMessage(SCI_SELECTALL); + break; + } +return TRUE; +} + + +/******************************************************************** +* Class: CManager. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CManager::CManager(){ +} + +CManager::~CManager(){ +} + +void CManager::OpenFileDialog(void){ + CFileItem * file = new CFileItem; + + /* Show the "Open file" dialog */ + winApp.FileDlg.Reset(); + winApp.FileDlg.SetInitialDir(winApp.openFilesDir); + + if(!winApp.FileDlg.Open(&winApp, file->szFileName, MAX_PATH, SRC_FILE)){ + delete file; + return; // canceled by user + } + + /* Get file information */ + file->nFileExtension = winApp.FileDlg.GetFileExtension(); + file->nFileOffset = winApp.FileDlg.GetFileOffset(); + GetFileType(file); + // Copy file directory. + strncpy(winApp.openFilesDir, file->szFileName, (file->nFileOffset - 1)); + winApp.openFilesDir[file->nFileOffset-1] = '\0'; + + /* Load the file */ + if(!OpenFile(file)){ + delete file; + MsgBox.DisplayString("This file is already opened."); + } +} + +bool CManager::OpenFile(CFileItem * file){ + if (!file) + return false; + + if (!file->isInProject){ + if (!FilesView.OpenFile(file)) + return false; + }else{ + if (!ProjectView.OpenFile(file)) + return false; + } +return true; +} + +bool CManager::NewProjectDialog(void){ + if(IDYES == Project.CloseDecision()) + CloseProject(); + + char fileName[MAX_PATH]; + WORD fileOffset; + *fileName = '\0'; + + + if (!winApp.FileDlg.Save(&winApp, fileName, MAX_PATH, PRJ_FILE)){ + return false; // canceled by user + } + // Copy prj file's directory. + fileOffset = winApp.FileDlg.GetFileOffset(); + + ProjectView.CreateRoot("Project"); + if (!Project.New(fileName, fileOffset)){ + ProjectView.DestroyRoot(); + ProjectView.DestroyList(); + return false; + } +return true; +} + +bool CManager::OpenProjectDialog(void){ + if(IDYES == Project.CloseDecision()) + CloseProject(); + + char fileName[MAX_PATH]; + WORD offset; + *fileName = '\0'; + + // Load default values. + winApp.FileDlg.Reset(); + winApp.FileDlg.SetInitialDir(winApp.projectDir); + + if (!winApp.FileDlg.Open(&winApp, fileName, MAX_PATH, PRJ_FILE)){ + return false; // canceled by user + } + // Copy project file's directory. + offset = winApp.FileDlg.GetFileOffset(); + + // Initialize project tree view. + ProjectView.CreateRoot(fileName+offset); + + if (!Project.Open(fileName, offset)){ + ProjectView.DestroyRoot(); + ProjectView.DestroyList(); + return false; + } +return true; +} + +bool CManager::CloseProject(void){ +return ProjectView.Close(); +} + +void CManager::RemoveProjectFile(void){ + ProjectView.RemoveFile(); +} + +void CManager::RemoveProjectModule(void){ + ProjectView.RemoveModule(); +} + +int CManager::SaveProjectFiles(int decision){ +return ProjectView.SaveAll(decision); +} + +int CManager::SaveAll(int decision){ + /* Save open files ? */ + decision = FilesView.SaveAll(decision); + /* Save project files ? */ + decision = ProjectView.SaveAll(decision); +return decision; +} + +void CManager::CreateImageList(void){ + // Create an empty image list. + ImgList.Create(16, 16, ILC_COLORDDB|ILC_MASK, 8, 1); + + // Load treeview bmp and add it to the image list. + CBitmap tvBitmap; + tvBitmap.Load(this, IDB_TREEVIEW); + ImgList.AddMasked(&tvBitmap, RGB(255,0,255)); + + // We no longer need treeview bmp. + tvBitmap.Destroy(); +} + +void CManager::Create(CWindow * pParent){ + // Create the Tab Control. + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | TCS_BOTTOM | TCS_FOCUSNEVER); + + // Give it the default font, create tabs, select first one and show the control. + SendMessage(WM_SETFONT, (long) GetStockObject(DEFAULT_GUI_FONT), 0); + + InsertItem(FILES_TAB, TCIF_TEXT, 0, 0, "Files", 16, 0, 0); + InsertItem(PROJECT_TAB, TCIF_TEXT, 0, 0, "Project", 16, 0, 0); + Show(); + + // Create an Image list and then the Project TreeView. + CreateImageList(); + ProjectView.Create(this, &ImgList); + SetItem_Param(PROJECT_TAB, (long) &ProjectView); + FilesView.Create(this, &ImgList); + SetItem_Param(FILES_TAB, (long) &FilesView); +} + +bool CManager::SetPosition(HWND, int x, int y, int width, int height, UINT){ + /* Overwrites CTabCtrl::SetPosition() so that all child windows are also resized */ + + // Tab Control. + ::SetWindowPos(_hWnd, 0, + x, + y, + width, + height, + 0); + // Child windows. + RECT Rect; + ::GetClientRect(_hWnd, &Rect); + ProjectView.SetPosition(0, Rect.top +5, Rect.left +5, + Rect.right-10, Rect.bottom-30, 0); + + FilesView.SetPosition(0, Rect.top +5, Rect.left +5, + Rect.right-10, Rect.bottom-30, 0); +return true; +} + +BOOL CManager::OnNotify(int, LPNMHDR notify){ + // Dispatch messages. + switch (notify->code){ + // Tab Control. + case TCN_SELCHANGING: + OnSelChanging(notify); + break; + + case TCN_SELCHANGE: + OnSelChange(notify); + break; + + // TreeView. + case TVN_SELCHANGED: + Tv_OnSelchanged((LPNMTREEVIEW) notify); + break; + } +return TRUE; +} + +void CManager::OnSelChanging(LPNMHDR notify){ + if (_hWnd == notify->hwndFrom){ + CTreeView * pTreeView = (CTreeView *) GetItem_Param(GetCurSel()); + if (pTreeView){ + pTreeView->Hide(); + } + } +} + +void CManager::OnSelChange(LPNMHDR notify){ + if (_hWnd == notify->hwndFrom){ + CTreeView * pTreeView = (CTreeView *) GetItem_Param(GetCurSel()); + if (pTreeView){ + pTreeView->Show(); + } + } +} + +void CManager::Tv_OnSelchanged(LPNMTREEVIEW notify){ + // Get lParam of current tree item. + CFileItem * file = (CFileItem *) notify->itemNew.lParam; + + if (file){ + CChildView * pMdiChild = (CChildView *) file->pMdiChild; + + if(pMdiChild){ + // An editor, focus it. + ::SetFocus((HWND) pMdiChild->_hWnd); + }else{ + // No editor, the item is part of a project. + Project.SwitchCurrentDir(); + winApp.CreateChild(file->szFileName, file); + } + } +} + + +/******************************************************************** +* Class: CFilesView. +* +* Purpose: Open files TreeView. +* +* Revisions: +* +********************************************************************/ +CFilesView::CFilesView(){ + hRoot = NULL; +} + +CFilesView::~CFilesView(){ +} + +void CFilesView::New(void){ + CFileItem * file = new CFileItem; + if(!winApp.Manager.OpenFile(file)){ + delete file; + MsgBox.DisplayString("Untitled file already exist."); + } +} + +bool CFilesView::OpenFile(CFileItem * file){ + if (!file) + return false; + + int listAction; + char * fileName = file->szFileName + file->nFileOffset; + + /* Untitled file ? */ + if (file->nFileOffset == 0){ + //@@TODO add a counter to get Untitled01, 02, etc... + strcpy(file->szFileName, "Untitled"); + } + + /* Check if this file is already opened */ + listAction = InsertSorted_New(file); + + if (listAction == FILE_FOUND){ + /* Focus the editor window */ + CFileItem * currentFile = (CFileItem *) GetCurrent(); + if (currentFile){ + CMDIChild * pMdiChild = currentFile->pMdiChild; + if (pMdiChild) + pMdiChild->SetFocus(); + } + return false; + } + + /* Create the editor window */ + if (!winApp.CreateChild(file->szFileName, file)){ + MsgBox.DisplayFatal("Can't create child window"); + return false; + } + // Note: A WM_SETFOCUS message will be send to the child window. + + /* Append the file to the list */ + InsertLast(file); + + /* Create a Tree View item */ + file->_hItem = CreateItem( + hRoot, //@@ use a GetRootItem() ? + TVI_LAST, + file->type, + fileName, + (LPARAM) file); + + file->pTreeView = this; +return true; +} + +void CFilesView::CloseFile(CFileItem * file){ + SendMessage(TVM_DELETEITEM, 0, (LPARAM) file->_hItem); + Destroy(file); +} + +int CFilesView::SaveAll(int decision){ + if (decision == IDNO || decision == IDCANCEL) + return decision; + CFileItem * file = (CFileItem*) First(); + while (file){ + if (file->pMdiChild){ + CChildView * childView = (CChildView *) file->pMdiChild; + /* Modified ? */ + if (childView->modified){ + /* Ask ? */ + if (decision == IDASK){ + decision = MsgBox.AskToSave(true); // Cancel button. + if (decision != IDYES) + return decision; // IDNO or IDCANCEL. + } + childView->CmdSave(); + } + } + file = (CFileItem*) Next(); + } +return decision; +} + +HWND CFilesView::Create(CWindow * pParent, CImageList * imgList){ + // Create TreeView. + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS, + 0, + (void*) 12); + + // Assign the image list to the treeview control. + SendMessage(TVM_SETIMAGELIST, (long)TVSIL_NORMAL, (long) imgList->GetId()); + hRoot = CreateItem(TVI_ROOT, TVI_LAST, WORKSPACE, "Workspace", 0); +return _hWnd; +} + + +/******************************************************************** +* Class: CProjectView. +* +* Purpose: Project TreeView. +* +* Revisions: +* +********************************************************************/ +CProjectView::CProjectView(){ + hRoot = NULL; +} + +CProjectView::~CProjectView(){ +} + +CFileItem * CProjectView::NewFile(char * name){ + CFileItem * current = (CFileItem *) GetCurrent(); + CFileItem * srcFile = new CFileItem; + + // Copy directory name. + if (current){ + strncpy(srcFile->szFileName, current->szFileName, current->nFileOffset); + srcFile->nFileOffset = current->nFileOffset; + }else{ + // No files in the project yet, use makefile directory. + strcpy(srcFile->szFileName, Project.Makefile.mkfDir); + srcFile->nFileOffset = strlen(srcFile->szFileName)+1; + } + + srcFile->szFileName[srcFile->nFileOffset - 1] = '\\'; + + // Append file name. + strcpy(&srcFile->szFileName[srcFile->nFileOffset], name); + //MsgBox.DisplayString(srcFile->szFileName); + + if (::CheckFile(srcFile)){ + ::GetFileType(srcFile); + srcFile->isInProject = true; + HANDLE hFile; + hFile = ::CreateFile(srcFile->szFileName, + 0, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_ARCHIVE, + NULL); + + if (hFile != INVALID_HANDLE_VALUE){ + CloseHandle(hFile); + // Try to add new file to the project. + if(OpenFile(srcFile)){ + Project.modified = true; + return srcFile; + } + } + } + delete srcFile; +return NULL; +} + +bool CProjectView::OpenFile(CFileItem * file){ + if (!file) + return false; + + int listAction; + char * fileName = file->szFileName + file->nFileOffset; + + /* Check if this file is already opened */ + listAction = InsertSorted_New(file); + + if (listAction == FILE_FOUND){ + /* Focus the editor window */ + CFileItem * currentFile = (CFileItem *) GetCurrent(); + if (currentFile){ + CMDIChild * pMdiChild = currentFile->pMdiChild; + if (!pMdiChild){ + /* Create a child window */ + Project.SwitchCurrentDir(); + winApp.CreateChild(file->szFileName, file); + }else{ + pMdiChild->SetFocus(); + } + } + return false; + } + + file->_hDirItem = hRoot; + CreateSubDirItem(file); + + if (listAction == EMPTY_LIST){ + InsertFirst(file); + }else if (listAction == INSERT_FIRST){ + InsertFirst(file); + }else if (listAction == INSERT_LAST){ + InsertLast(file); + }else if (listAction == INSERT_BEFORE){ + InsertBefore(file); + }else if (listAction == INSERT_AFTER){ + InsertAfter(file); + } + + /* Create the file icon */ + file->_hItem = CreateItem( + file->_hDirItem, + TVI_SORT, + file->type, + fileName, + (LPARAM) file); + + file->pTreeView = this; + + /* Create an editor view */ + if (file->show){ + winApp.CreateChild(file->szFileName, file); + } +return true; +} + +bool CProjectView::Close(){ + if (Project.NoProject()) + return false; + + int decision = IDASK; + decision = SaveAll(decision); + if (decision == IDCANCEL) + return false; + + // Parse the list while there's a next node. + CFileItem * srcFile = (CFileItem *) First(); + while(srcFile){ + DestroyFile(srcFile, decision); + srcFile = (CFileItem *) Next(); + } + Project.loaded = false; + + DestroyRoot(); + DestroyList(); + winApp.Report.Clear(); +return true; +} + +void CProjectView::RemoveFile(void){ + if (Project.NoProject()) + return; + + CFileItem * srcFile = (CFileItem *) GetSelectedItemParam(); + + if (srcFile){ + if (srcFile->pMdiChild) + DestroyFile(srcFile); + TreeView_DeleteItem(_hWnd, srcFile->_hItem); + if (!TreeView_GetChild(_hWnd, srcFile->_hDirItem)) + TreeView_DeleteItem(_hWnd, srcFile->_hDirItem); +/* else + TreeView_SelectItem(_hWnd, srcFile->_hDirItem);*/ + Destroy(srcFile); + + // we need to save prj file before exit. + //@@ Project.CloseFile, modified & buildMakefile should be private. + Project.modified = true; + Project.buildMakefile = true; + }else{ + MsgBox.DisplayWarning("No project file selected"); + } +} + +void CProjectView::RemoveModule(void){ + if (Project.NoProject()) + return; + + CFileItem * srcFile = (CFileItem *) GetSelectedItemParam(); + CFileItem * otherFile; + + if (srcFile){ + if (srcFile->prev){ + otherFile = (CFileItem *) srcFile->prev; + if (otherFile->nFileExtension != 0){ + if (0 == strnicmp(srcFile->szFileName, otherFile->szFileName, otherFile->nFileExtension)){ + if (otherFile->pMdiChild) + DestroyFile(otherFile); + TreeView_DeleteItem(_hWnd, otherFile->_hItem); + Destroy(otherFile); + } + } + } + if (srcFile->next){ + otherFile = (CFileItem *) srcFile->next; + if (otherFile->nFileExtension != 0){ + if (0 == strnicmp(srcFile->szFileName, otherFile->szFileName, otherFile->nFileExtension)){ + if (otherFile->pMdiChild) + DestroyFile(otherFile); + TreeView_DeleteItem(_hWnd, otherFile->_hItem); + Destroy(otherFile); + } + } + } + if (srcFile->pMdiChild) + DestroyFile(srcFile); + TreeView_DeleteItem(_hWnd, srcFile->_hItem); + Destroy(srcFile); + + // we need to save prj file before exit. + //@@ Project.CloseFile, modified & buildMakefile should be private. + Project.modified = true; + Project.buildMakefile = true; + }else{ + MsgBox.DisplayWarning("No project file selected"); + } +} + +int CProjectView::DestroyFile(CFileItem * file, int decision){ + if (file && file->pMdiChild){ + CChildView * pMdiChild = (CChildView *) file->pMdiChild; + + if (pMdiChild->modified && decision != IDNO){ + // Ask ? + if (decision == IDASK){ + decision = MsgBox.AskToSave(true); // (Cancel button) + if (decision == IDCANCEL) + return decision; + } + pMdiChild->CmdSave(); + } + + if (pMdiChild->_hWnd) // have an editor window, so destroy it. + winApp.MdiClient.SendMessage(WM_MDIDESTROY, (WPARAM)pMdiChild->_hWnd, 0); + } +return decision; +} + +int CProjectView::SaveAll(int decision){ + if (!Project.loaded) + return 0; + + if (decision == IDNO || decision == IDCANCEL) + return decision; + + CFileItem * file = (CFileItem*) First(); + while (file){ + if (file->pMdiChild){ + CChildView * childView = (CChildView *) file->pMdiChild; + /* Modified ? */ + if (childView->modified){ + /* Ask ? */ + if (decision == IDASK){ + decision = MsgBox.AskToSave(true); // Cancel button. + if (decision != IDYES) + return decision; // IDNO or IDCANCEL. + } + childView->CmdSave(); + } + } + file = (CFileItem*) Next(); + } + + if (Project.modified) + return Project.SavePrjFile(decision); +return decision; +} + +bool CProjectView::CreateSubDirItem(CFileItem * file){ + /* Initialize _hDirItem and get a pointer to current file */ + file->_hDirItem = hRoot; + CFileItem * currentFile = (CFileItem *) GetCurrent(); + + /* See if our new file is in the same directory than current file */ + if (currentFile){ + // There's some files in the list. + if (file->nFileOffset == currentFile->nFileOffset){ + // Same directory length, we may have found the directory. + if (0 == strnicmp(file->szFileName, currentFile->szFileName, currentFile->nFileOffset)){ + /* We have found the directory, then copy _hDirItem */ + file->_hDirItem = currentFile->_hDirItem; + return true; + } + } + } + + /* We need to parse the tree view and create directory icons */ + char * parse = file->szFileName; + if (*parse == '.' && *(parse+1) == '\\'){ + /* This is a valid relative path */ + char dir[MAX_PATH]; + strcpy(dir, file->szFileName); + parse = dir+2; + char * dirStart; + HTREEITEM hParent = hRoot; + HTREEITEM hFound; + if (*parse){ + for ( ; ; ){ + /* Found each backslash */ + dirStart = parse; + parse = strchr(parse, '\\'); + if (!parse) + break; // No more backslash. + else if (parse == dirStart) + return false; // Avoids an endless loop. + *parse = '\0'; + + /* Find the directory */ + hFound = FindDirItem(hParent, dirStart); + if (!hFound){ + /* Append a new directory icon */ + hParent = CreateDirItem(hParent, dirStart); + } + parse++; + } + } + file->_hDirItem = hParent; + } +return true; +} + +HTREEITEM CProjectView::FindDirItem(HTREEITEM hItem, char * dir){ + char buffer[_MAX_DIR]; + HTREEITEM hNext = TreeView_GetChild(_hWnd, hItem); + while (hNext){ + _TvItem.hItem = hNext; + _TvItem.mask = TVIF_HANDLE | TVIF_TEXT; + _TvItem.pszText = buffer; + _TvItem.cchTextMax = _MAX_DIR; + if (TreeView_GetItem(_hWnd, &_TvItem)){ + if (!stricmp(dir, buffer)) + return hNext; + } + hNext = TreeView_GetNextSibling(_hWnd, hNext); + } +return NULL; +} + +HWND CProjectView::Create(CWindow * pParent, CImageList * imgList){ + // Create TreeView. + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | TVS_EDITLABELS | TVS_HASLINES | TVS_HASBUTTONS); + + // Assign the image list to the treeview control. + SendMessage(TVM_SETIMAGELIST, (long)TVSIL_NORMAL, (long) imgList->GetId()); +return _hWnd; +} + +void CProjectView::CreateRoot(char * projectName){ + + _pParent->SendMessage(TCM_SETCURFOCUS, 1, 0); + + // Create Root Item. + hRoot = CreateItem(TVI_ROOT, TVI_LAST, PROJECT, projectName, 0); + SendMessage(TVM_EXPAND, (long) TVE_EXPAND, (long) hRoot); +} + +void CProjectView::DestroyRoot(void){ + TreeView_DeleteItem(_hWnd, hRoot); + hRoot = 0; + + _pParent->SendMessage(TCM_SETCURFOCUS, 0, 0); +} + +HTREEITEM CProjectView::CreateDirItem(HTREEITEM hParent, char * dir){ +return CreateItem(hParent, TVI_SORT, DIR, dir, 0); +} + +CFileItem * CProjectView::FindFile(char * szFileName){ + if (!szFileName || !*szFileName) + return NULL; + + char * currentFile; + bool stripDir = true; + if (*szFileName == '.') + stripDir = false; + // Get the current node. + CFileItem * currentNode = (CFileItem *) GetCurrent(); + + if(!currentNode) + return NULL; // The list is empty. + + currentFile = GetFileName(currentNode, stripDir); + int cmpResult = stricmp(szFileName, currentFile); + // Compare names to know if we must parse Up + // or Down from current node. + if (cmpResult == 0){ + return currentNode; // Found ! + } + // Search Up ----------------------------------------------------------------- + else if (cmpResult == -1){ + // Parse the list while there's a previous node. + while (Prev()){ + currentNode = (CFileItem *) GetCurrent(); + currentFile = GetFileName(currentNode, stripDir); + if(!stricmp(szFileName, currentFile)) + return currentNode; // Found ! + } + } + // Search Down -------------------------------------------------------------- + else if (cmpResult == 1){ + // Parse the list while there's a next node. + while (Next()){ + currentNode = (CFileItem *) GetCurrent(); + currentFile = GetFileName(currentNode, stripDir); + if(!stricmp(szFileName, currentFile)) + return currentNode; // Found ! + } + } +return NULL; +} + +char * CProjectView::GetFileName(CFileItem * currentNode, bool flag){ + char * fileName = currentNode->szFileName; + if (flag == true){ + fileName += currentNode->nFileOffset; + } +return fileName; +} + + +/******************************************************************** +* Class: CReport. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CReport::CReport(){ +} + +CReport::~CReport(){ +} + +void CReport::Create(CWindow * pParent){ + // Create the Tab Control. + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + /*| TCS_BOTTOM*/ | TCS_MULTILINE | TCS_VERTICAL + | TCS_FOCUSNEVER); + + // Give it a smart font, create tabs, select first one and show the control. + SendMessage(WM_SETFONT, (long) GetStockObject(DEFAULT_GUI_FONT), 0); + + InsertItem(REPORT_MAIN_TAB, TCIF_TEXT, 0, 0, "Main", 16, 0, 0); + InsertItem(REPORT_LOG_TAB, TCIF_TEXT, 0, 0, "Log", 16, 0, 0); + Show(); + + // Create an Image list and then the Project TreeView. + MainList.Create(this); + SetItem_Param(REPORT_MAIN_TAB, (long) &MainList); + LogList.Create(this); + SetItem_Param(REPORT_LOG_TAB, (long) &LogList); +} + +bool CReport::SetPosition(HWND, int x, int y, int width, int height, UINT){ + /* Overwrites CTabCtrl::SetPosition() so that all child windows are also resized */ + + // Tab Control. + ::SetWindowPos(_hWnd, 0, + x, + y, + width, + height, + 0); + + // Get tab's display area. + RECT area; + area.left = 0; + area.top = 0; + area.right = width; + area.bottom = height; + ::SendMessage(_hWnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &area); + area.right -= area.left; + area.bottom -= area.top; + /* WS_EX_CLIENTEDGE correction */ + area.top -= 2; + area.right -= 2; + // Borders. + area.left += 3; + area.top += 3; + area.right -= 6; + area.bottom -= 6; + + // Child windows. + MainList.SetPosition(0, area.left, area.top, + area.right, area.bottom, 0); + LogList.SetPosition(0, area.left, area.top, + area.right, area.bottom, 0); +return true; +} + +BOOL CReport::OnNotify(int, LPNMHDR notify){ + // Dispatch messages. + switch (notify->code){ + // Tab Control. + case TCN_SELCHANGING: + OnSelChanging(notify); + break; + + case TCN_SELCHANGE: + OnSelChange(notify); + break; + + // Main list. + case NM_DBLCLK: + MainList.Lv_OnDbClick((LPNMLISTVIEW) notify); + break; + } +return TRUE; +} + +void CReport::OnSelChanging(LPNMHDR notify){ + if (_hWnd == notify->hwndFrom){ + CWindow * pWindow = (CWindow *) GetItem_Param(GetCurSel()); + if (pWindow){ + pWindow->Hide(); + } + } +} + +void CReport::OnSelChange(LPNMHDR notify){ + if (_hWnd == notify->hwndFrom){ + CWindow * pWindow = (CWindow *) GetItem_Param(GetCurSel()); + if (pWindow){ + pWindow->Show(); + } + } +} + +void CReport::Clear(void){ + MainList.Clear(); + LogList.Clear(); +} + +bool CReport::Append(char * line, WORD outputFlag){ + LogList.Append(line, outputFlag); + MainList.Append(line, outputFlag); +return true; +} + + +/******************************************************************** +* Class: CMainList. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CMainList::CMainList(){ +} + +CMainList::~CMainList(){ +} + +void CMainList::Create(CWindow * pParent){ + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_VISIBLE | WS_CHILD| WS_CLIPCHILDREN | WS_CLIPSIBLINGS + | LVS_REPORT); + + SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, + LVS_EX_GRIDLINES, LVS_EX_GRIDLINES); + SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + // Insert columns. + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.cx = 35; + lvc.pszText = "Line"; + SendMessage(LVM_INSERTCOLUMN, 0, (LPARAM) &lvc); + + lvc.iSubItem = 1; + lvc.cx = 70; + lvc.pszText = "Unit"; + SendMessage(LVM_INSERTCOLUMN, 1, (LPARAM) &lvc); + + lvc.iSubItem = 2; + lvc.cx = 640; + lvc.pszText = "Message"; + SendMessage(LVM_INSERTCOLUMN, 2, (LPARAM) &lvc); +} + +void CMainList::Lv_OnDbClick(LPNMLISTVIEW lpnmlv){ + if (_hWnd == lpnmlv->hdr.hwndFrom){ + char lineBuff[256]; + *lineBuff = '\0'; + char * c = lineBuff; + LV_ITEM lvi; + lvi.mask = LVIF_TEXT; + lvi.iItem = lpnmlv->iItem; + lvi.iSubItem = 0; + lvi.pszText = lineBuff; + lvi.cchTextMax = 256; + lvi.lParam = 0; + if (!SendMessage(LVM_GETITEMTEXT, lpnmlv->iItem, (long) &lvi)) + return; + while(*c){ + if (!isdigit(*c)) + return; + c++; + } + int line = atoi(lineBuff); + + //MsgBox.DisplayLong((long) line); + + lvi.iSubItem = 1; + if (!SendMessage(LVM_GETITEMTEXT, lpnmlv->iItem, (long) &lvi)) + return; + CFileItem * item = winApp.Manager.ProjectView.FindFile(lineBuff); + if (item && item->isInProject){ + CChildView * pMdiChild = (CChildView *) item->pMdiChild; + + if(pMdiChild){ + // An editor, focus it. + ::SetFocus((HWND) pMdiChild->_hWnd); + }else{ + // No editor, the item is part of a project. + Project.SwitchCurrentDir(); + winApp.CreateChild(item->szFileName, item); + } + pMdiChild = (CChildView *) item->pMdiChild; + if (pMdiChild) + pMdiChild->Editor.GotoLine(line-1); + } + } +} + +bool CMainList::Append(char * line, WORD outputFlag){ + int row; + + *szLine = '\0'; + *szUnit = '\0'; + *szMsg = '\0'; + + if (outputFlag == LVOUT_ERROR){ + if (!SplitErrorLine(line)) + return false; + }else if (outputFlag == LVOUT_NORMAL){ + strcpy (szMsg, line); + }else{ + strcpy (szMsg, "Unrecognized outputFlag"); + } + + // Fill in List View columns, first is column 0. + LV_ITEM lvi; + lvi.mask = LVIF_TEXT; // | LVIF_PARAM; + lvi.iItem = 0x7FFF; + lvi.iSubItem = 0; + lvi.pszText = szLine; + lvi.cchTextMax = strlen(lvi.pszText)+1; + lvi.lParam = 0; + + row = SendMessage(LVM_INSERTITEM, 0, (LPARAM) &lvi); + + // Continue with column 1. + lvi.iSubItem = 1; + lvi.pszText = szUnit; + lvi.cchTextMax = strlen(lvi.pszText)+1; + SendMessage(LVM_SETITEMTEXT, (WPARAM)row, (LPARAM)&lvi); + + // Continue with column 2. + lvi.iSubItem = 2; + lvi.pszText = szMsg; + lvi.cchTextMax = strlen(lvi.pszText)+1; + SendMessage(LVM_SETITEMTEXT, (WPARAM)row, (LPARAM)&lvi); + + // Save last row position + lastRow = row+1; + +return true; +} + +bool CMainList::SplitErrorLine(char * line){ + char * chr = line; + char * col; + // line => [unit]:[line_n°]: [error message] + // or => [unit]: [error message] + + if (!*line) + return false; + + /* Unit */ + col = szUnit; + for ( ; ; ){ + if (!*chr){ + /* Not an error line */ + //strcpy(szMsg, szUnit); + *szUnit = '\0'; + return false; + }else if (*chr == ':'){ + if (*(chr+1) == '\\'){ + *col = *chr; + col++; + chr++; + continue; + }else{ + chr++; + break; + } + } + *col = *chr; + col++; + chr++; + } + *col = '\0'; + + /* Line number ? */ + col = szLine; + if (*chr && isdigit(*chr)){ //@@ *chr=0 ? + while (*chr && *chr != ':'){ + *col = *chr; + col++; + chr++; + } + *col = '\0'; + chr++; + } + + /* Message */ + col = szMsg; + if (isspace(*chr)){ + /**col = '>'; + col++; + *col = ' '; + col++;*/ + chr++; + } + + while (*chr){ + *col = *chr; + col++; + chr++; + } + *col = '\0'; +return true; +} + + +/******************************************************************** +* Class: CLogList. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CLogList::CLogList(){ +} + +CLogList::~CLogList(){ +} + +void CLogList::Create(CWindow * pParent){ + CreateEx( + pParent, + WS_EX_CLIENTEDGE, + WS_CHILD| WS_CLIPCHILDREN | WS_CLIPSIBLINGS | LVS_REPORT + | LVS_NOCOLUMNHEADER); + + SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + // Insert columns. + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.cx = 100; + lvc.pszText = "Message"; + SendMessage(LVM_INSERTCOLUMN, 0, (LPARAM) &lvc); +} + +bool CLogList::SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags){ + ::SendMessage(_hWnd, WM_SETREDRAW, FALSE, 0); + ::SetWindowPos(_hWnd, hInsertAfter, x, y, width, height, uFlags); + ::SendMessage(_hWnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM((int) width-22, 0)); + ::SendMessage(_hWnd, WM_SETREDRAW, TRUE, 0); +return true; +} + +bool CLogList::Append(char * line, WORD /*outputFlag*/){ + int row; + + *szMsg = '\0'; + +/* if (outputFlag != LVOUT_ERROR) + return false; +*/ + // Fill in List View columns, first is column 0. + LV_ITEM lvi; + lvi.mask = LVIF_TEXT; // | LVIF_PARAM; + lvi.iItem = 0x7FFF; + lvi.iSubItem = 0; + lvi.pszText = line; + lvi.cchTextMax = strlen(lvi.pszText)+1; + lvi.lParam = 0; + + row = SendMessage(LVM_INSERTITEM, 0, (LPARAM) &lvi); + + // Save last row position + lastRow = row+1; + +return true; +} + + +/******************************************************************** +* Class: CFileItem. +* +* Purpose: Linked List Node for file parameters. +* +* Revisions: +* +********************************************************************/ +CFileItem::CFileItem(){ + type = U_FILE; + + *szFileName = '\0'; + szFileName[MAX_PATH - 1] = '\0'; // security. + nFileOffset = 0; + nFileExtension = 0; + + pTreeView = NULL; + _hDirItem = 0; + _hItem = 0; + + pMdiChild = NULL; + show = 0; + isInProject = false; +} + +CFileItem::~CFileItem(){ +} + + +/******************************************************************** +* Class: CFileList. +* +* Purpose: A CList with a dedicated Compare() procedure. +* +* Revisions: +* +********************************************************************/ +CFileList::CFileList(){ +} + +CFileList::~CFileList(){ +} + +int CFileList::Compare(CNode *node1, CNode *node2){ +return stricmp(((CFileItem *)node1)->szFileName, ((CFileItem *)node2)->szFileName); +} + diff --git a/rosapps/devutils/vmingw/main.h b/rosapps/devutils/vmingw/main.h new file mode 100644 index 00000000000..4aa4cc70a52 --- /dev/null +++ b/rosapps/devutils/vmingw/main.h @@ -0,0 +1,385 @@ +/******************************************************************** +* Module: main.h. This is part of Visual-MinGW. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#ifndef MAIN_H +#define MAIN_H + +#include "CList.h" +#include "winui.h" +#include "editor.h" +#include "process.h" + +#define LVOUT_NORMAL (STDOUT_USER) +#define LVOUT_ERROR (STDOUT_USER+1) +#define IDASK 21 + +#define WORKSPACE 0 +#define PROJECT 1 +#define DIR 2 + +#define PRJ_FILE 0 +#define SRC_FILE 1 +#define ADD_SRC_FILE 2 + +#define FILES_TAB 0 +#define PROJECT_TAB 1 + +#define REPORT_MAIN_TAB 0 +#define REPORT_LOG_TAB 1 + + +class CChildView : public CMDIChild +{ + public: + CChildView(); + virtual ~CChildView(); + + bool modified; + + bool OnCreate(LPCREATESTRUCT lParam); + bool OnSize(UINT wParam, int width, int height); + BOOL OnClose(void); + BOOL OnDestroy(void); + + BOOL OnCommand(WPARAM wParam, LPARAM lParam); + BOOL OnNotify(int idCtrl, LPNMHDR notify); + BOOL OnSetFocus(HWND hwndLoseFocus); + BOOL OnActivate(HWND hwndChildDeact, HWND hwndChildAct); + + void CmdSave(void); + void CmdSaveAs(void); + CEditor Editor; + + protected: + + private: +}; + +class CFileList : public CList +{ + public: + CFileList(); + ~CFileList(); + + protected: + virtual int Compare(CNode *node1, CNode *node2); + + private: +}; + +class CProjectView : public CTreeView, public CFileList +{ + public: + CProjectView(); + ~CProjectView(); + + CFileItem * NewFile(char * name); + bool OpenFile(CFileItem * file); + void RemoveFile(void); + void RemoveModule(void); + int DestroyFile(CFileItem * file, int decision=IDASK); + int SaveAll(int decision); + bool Close(); + + void CreateRoot(char * projectName); + void DestroyRoot(void); + CFileItem * FindFile(char * szFileName); + char * GetFileName(CFileItem * currentNode, bool flag); + + HWND Create(CWindow * pParent, CImageList * imgList); + HTREEITEM CreateDirItem(HTREEITEM hParent, char * dir); + + protected: + + private: + bool CreateSubDirItem(CFileItem * file); + HTREEITEM FindDirItem(HTREEITEM hItem, char * dir); + HTREEITEM hRoot; +}; + +class CFilesView : public CTreeView, public CFileList +{ + public: + CFilesView(); + ~CFilesView(); + + bool OpenFile(CFileItem * file); + void New (void); + void CloseFile(CFileItem * file); + int SaveAll(int decision); + + HWND Create(CWindow * pParent, CImageList * imgList); + + protected: + + private: + HTREEITEM hRoot; +}; + +class CManager : public CTabCtrl +{ + public: + CManager(); + ~CManager(); + + void OpenFileDialog(void); + bool OpenFile(CFileItem * file); + int SaveAll(int silent); + + bool NewProjectDialog(void); + bool OpenProjectDialog(void); + bool CloseProject(void); + int SaveProjectFiles(int decision); + void RemoveProjectFile(void); + void RemoveProjectModule(void); + + void Create(CWindow * pParent); + bool SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags); + + BOOL OnNotify(int idCtrl, LPNMHDR notify); + void Tv_OnDeleteItem(LPNMTREEVIEW notify); + void Tv_OnSelchanged(LPNMTREEVIEW notify); + void OnSelChanging(LPNMHDR notify); + void OnSelChange(LPNMHDR notify); + + CImageList ImgList; + CFilesView FilesView; + CProjectView ProjectView; + + protected: + + private: + void CreateImageList(void); + +}; + +class CLogList : public CListView +{ + public: + CLogList(); + ~CLogList(); + + void Create(CWindow * pParent); + bool SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags); + bool Append(char * line, WORD outputFlag); + + protected: + + private: + char szMsg[1024]; +}; + +class CMainList : public CListView +{ + public: + CMainList(); + ~CMainList(); + + void Create(CWindow * pParent); + void Lv_OnDbClick(LPNMLISTVIEW lpnmlv); + bool Append(char * line, WORD outputFlag); + + protected: + + private: + char szLine[512]; + char szUnit[512]; + char szMsg[512]; + + bool SplitErrorLine(char * line); +}; + +class CReport : public CTabCtrl +{ + public: + CReport(); + ~CReport(); + + bool Append(char * line, WORD outputFlag); + void Clear(void); + void Create(CWindow * pParent); + bool SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags); + + BOOL OnNotify(int idCtrl, LPNMHDR notify); + void OnSelChanging(LPNMHDR notify); + void OnSelChange(LPNMHDR notify); + + CMainList MainList; + CLogList LogList; + + protected: + + private: + void CreateImageList(void); +}; + +class CFileDlg : public CFileDlgBase +{ + public: + CFileDlg(); + ~CFileDlg(); + + bool Open(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag); + bool Save(CWindow * pWindow, char * pszFileName, DWORD nMaxFile, int fileflag); + + protected: + + private: +}; + +class CGrepDlg : public CDlgBase +{ + public: + CGrepDlg(); + ~CGrepDlg(); + + int Create(void); + LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + void FindInFiles(char * findWhat, char * fileFilter); + char gDir[MAX_PATH]; + char findWhat[200]; + + protected: + + private: + HWND hFindWhat; + HWND hgDir; +}; + +class CEnvDlg : public CDlgBase +{ + public: + CEnvDlg(); + virtual ~CEnvDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + void SetEnvText(void); + bool bIsVisible; + bool bModified; + + protected: + + private: + HWND hApply; + HWND hSetCcBin; + HWND hCcBinDir; + HWND hBrowseCc; + HWND hSetCmdBin; + HWND hCmdBinDir; + HWND hBrowseCmd; + HWND hAutoexec; + HWND hEnvView; +}; + +class CPreferencesDlg : public CTabbedDlg +{ + public: + CPreferencesDlg(); + virtual ~CPreferencesDlg(); + + int Create(void); + BOOL EndDlg(int nResult); + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CEnvDlg EnvDlg; +}; + +class CWinApp : public CMDIBase +{ + public: + CWinApp(); + ~CWinApp(); + + void FirstRunTest(void); + bool ReadIniFile(char * iniFile); + void SaveIniFile(FILE * file); + bool WriteIniFile(void); + bool CustomInit(void); + bool Release(void); + bool SetEnv(void); + + bool CreateUI(void); + void CreateToolbar(void); + void CreateSplitter(void); + void CreateMDI(void); + HWND CreateChild(char * caption, LPVOID lParam); + void CreateStatusBar(void); + + void SendCaretPos(int caretPos); + + // Main window. + LRESULT CALLBACK CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam); + + BOOL OnCreate(LPCREATESTRUCT lParam); + BOOL OnPaint(HDC wParam); + BOOL OnSize(UINT wParam, int width, int height); + BOOL OnDestroy(void); + BOOL OnClose (void); + BOOL OnNotify(int idCtrl, LPNMHDR notify); + + BOOL OnLButtonDown(short xPos, short yPos, UINT fwKeys); + BOOL OnMouseMove(short xPos, short yPos, UINT fwKeys); + BOOL OnLButtonUp(short xPos, short yPos, UINT fwKeys); + BOOL OnSetCursor(HWND hwnd, UINT nHittest, UINT wMouseMsg); + + BOOL OnCommand(WPARAM wParam, LPARAM lParam); + + // Child window. + LRESULT CALLBACK CChildWndProc(CWindow * pWnd, UINT Message, WPARAM wParam, LPARAM lParam); + + HMODULE hmod; + char iniFileName[MAX_PATH]; + CIniFile IniFile; + CPreferencesDlg PreferencesDlg; + CGrepDlg GrepDlg; + CShellDlg ShellDlg; + CFileDlg FileDlg; + CProcess Process; + + CToolBar Toolbar; + CSplitter MainSplitter; + CSplitter ChildSplitter; + CManager Manager; + CReport Report; + CStatusBar Sbar; + + /* Preferences */ + char openFilesDir[MAX_PATH]; + char projectDir[MAX_PATH]; + bool bSetCcEnv; + bool bSetCmdEnv; + bool bSetDefEnv; + char szCcBinDir[MAX_PATH]; + char szCmdBinDir[MAX_PATH]; + char includeDir[MAX_PATH]; + + protected: + + private: + bool firstRun; + // Child windows dimensions. + int deltaY; + int tbarHeight; + int sbarHeight; + int tvWidth; + int lvHeight; + + int hSplitter; + int vSplitter; +}; + +#endif diff --git a/rosapps/devutils/vmingw/process.cpp b/rosapps/devutils/vmingw/process.cpp new file mode 100644 index 00000000000..092f41b56ae --- /dev/null +++ b/rosapps/devutils/vmingw/process.cpp @@ -0,0 +1,682 @@ +/******************************************************************** +* Module: process.cpp. This is part of Visual-MinGW. +* +* Purpose: Procedures to invoke MinGW compiler. +* +* Authors: Manu B. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +* Note: The following article from MSDN explanes how to handle Callback +* procedures : +* Calling All Members: Member Functions as Callbacks. +* by Dale Rogerson. +* Microsoft Developer Network Technology Group. +* April 30, 1992. +* http://msdn.microsoft.com/archive/default.asp +* +* Revisions: +* +********************************************************************/ +#include +#include +#include +#include +#include +#include "process.h" +#include "project.h" +#include "main.h" +#include "rsrc.h" + +extern CCriticalSection CriticalSection; +extern CMessageBox MsgBox; +char errmsg[128]; + +// For winApp.isWinNT and winApp.Report.Append +extern CWinApp winApp; + +/******************************************************************** +* Class: CCommandDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CCommandDlg::CCommandDlg(){ + *cmdLine = '\0'; +} + +CCommandDlg::~CCommandDlg(){ +} + +HWND CCommandDlg::Create(void){ +return CreateParam(&winApp, IDD_COMMAND, 0); +} + +LRESULT CALLBACK CCommandDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CCommandDlg::OnInitDialog(HWND, LPARAM){ + hCmdLine = GetItem(IDC_CMDLINE); + + SetItemText(hCmdLine, cmdLine); + // Show the dialog. + Show(); +return TRUE; +} + +BOOL CCommandDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + GetItemText(hCmdLine, cmdLine, sizeof(cmdLine)); + //MsgBox.DisplayString(cmdLine); + winApp.Process.CommandLine(cmdLine); + return TRUE; + + case IDCANCEL: + EndDlg(IDCANCEL); + return FALSE; + } +return FALSE; +} + + +/******************************************************************** +* Class: CTask. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CTask::CTask(){ + *cmdLine = '\0'; + *szFileName = '\0'; + creationFlag = 0; + outputFlag = 0; +} + +CTask::~CTask(){ +} + + +/******************************************************************** +* Class: CStack. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CStack::CStack(){ + retBuf = NULL; +} + +CStack::~CStack(){ + DestroyList(); + if (retBuf) + delete retBuf; +} + +void CStack::DetachCurrent(void){ + // Empty list ? + if (current != NULL){ + CNode * node = current; + + // Detach node from the list. + if (node->next != NULL) + node->next->prev = node->prev; + if (node->prev != NULL) + node->prev->next = node->next; + + // Set current node. + if(node->next != NULL) + current = node->next; + else + current = node->prev; + + if (current == NULL){ + // Now, the list is empty. + first = last = NULL; + + }else if (first == node){ + // Detached node was first. + first = current; + + }else if (last == node){ + // Detached node was last. + last = current; + } + count--; + } +} + +/******************************************************************** +* Push/Pop/Flush. +********************************************************************/ +int CStack::Push(CTask * newTask){ + InsertLast(newTask); +return Length(); +} + +CTask * CStack::Pop(void){ + // Delete return buffer. + if (retBuf){ + delete retBuf; + retBuf = NULL; + } + + // Get first node. (FIFO stack) + retBuf = (CTask*) First(); + + // The Stack is empty ? + if (!retBuf) + return NULL; + + // Detach current node from the list. Return a pointer to it. + DetachCurrent(); +return retBuf; +} + +void CStack::Flush(void){ + DestroyList(); + if (retBuf) + delete retBuf; + retBuf = NULL; +} + + +/******************************************************************** +* Class: CPipes. +* +* Purpose: Creates needed pipes, depending on creationFlag. +* Like GNU Make does, we use an Handle array for our pipes. +* Parent Process Side is stdXXX[0] and Child Process Side is stdXXX[1]. +* +* Ex: PARENT ->[0]IN_PIPE[1]-> CHILD_IO ->[1]OUT_PIPE[0]-> PARENT +* ->[1]ERR_PIPE[0]-> PARENT +* Revisions: +* +********************************************************************/ +CPipes::CPipes(){ + hIn[0] = NULL; + hIn[1] = NULL; + hOut[0] = NULL; + hOut[1] = NULL; + hErr[0] = NULL; + hErr[1] = NULL; +} + +CPipes::~CPipes(){ +} + +bool CPipes::Create(WORD creationFlag, bool winNT){ + /* Create needed pipes according to creationFlag */ + /* Parent side of pipes is [0], child side is [1] */ + HANDLE hDup; + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + if (winNT){ + /* Create a security descriptor for Windows NT */ + SECURITY_DESCRIPTOR sd; + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)){ + sprintf(errmsg, "vm error: Process.cpp InitializeSecurityDescriptor(winNT) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)){ + sprintf(errmsg, "vm error: Process.cpp SetSecurityDescriptorDacl(winNT) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + sa.lpSecurityDescriptor = &sd; + } + + /* Input pipe */ + if (!CreatePipe(&hIn[1], &hIn[0], &sa, 0)){ + sprintf(errmsg, "vm error: Process.cpp CreatePipe(In) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + + if (!DuplicateHandle(GetCurrentProcess(), + hIn[0], + GetCurrentProcess(), + &hDup, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)){ + sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(In) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + CloseHandle(hIn[0]); + hIn[0] = hDup; + + /* Output pipe */ + if (!CreatePipe(&hOut[0], &hOut[1], &sa, 0)){ + sprintf(errmsg, "vm error: Process.cpp CreatePipe(Out) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + + if (!DuplicateHandle(GetCurrentProcess(), + hOut[0], + GetCurrentProcess(), + &hDup, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)){ + sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(Out) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + CloseHandle(hOut[0]); + hOut[0] = hDup; + + /* Error pipe */ + if (!(creationFlag & OUTERR_PIPE) && (creationFlag & ERR_PIPE)){ + if (!CreatePipe(&hErr[0], &hErr[1], &sa, 0)){ + sprintf(errmsg, "vm error: Process.cpp CreatePipe(Err) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + + if (!DuplicateHandle(GetCurrentProcess(), + hErr[0], + GetCurrentProcess(), + &hDup, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)){ + sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(Err) failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + } + CloseHandle(hErr[0]); + hErr[0] = hDup; + } +return true; +} + +bool CPipes::CloseChildSide(void){ +return Close(1); +} + +bool CPipes::CloseParentSide(void){ +return Close(0); +} + +bool CPipes::Close(int side){ + + if (side < 0 || side > 1) + return false; + + if (hIn[side]){ + CloseHandle(hIn[side]); + hIn[side] = NULL; + } + + if (hOut[side]){ + CloseHandle(hOut[side]); + hOut[side] = NULL; + } + + if (hErr[side]){ + CloseHandle(hErr[side]); + hErr[side] = NULL; + } +return true; +} + + +/******************************************************************** +* Class: CProcess. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CProcess::CProcess(){ + Running = false; + exitCode = 0; + + pi.hProcess = 0; + pi.hThread = 0; + pi.dwProcessId = 0; + pi.dwThreadId = 0; +} + +CProcess::~CProcess(){ +} + +/******************************************************************** +* Manage Tasks. +********************************************************************/ +bool CProcess::isRunning(void){ + if (Running){ + MsgBox.DisplayWarning("A process is already running !"); + return true; + } +return false; +} + +CTask * CProcess::AddTask(char * cmdLine, WORD creationFlag, WORD outputFlag){ + CTask * newTask = new CTask; + + strcpy(newTask->cmdLine, cmdLine); + newTask->creationFlag = creationFlag; + newTask->outputFlag = outputFlag; + Push(newTask); +return newTask; +} + +bool CProcess::CmdCat(char * cmdLine){ + CTask * task = (CTask*) GetCurrent(); + if (!task) + return false; + + strcat(task->cmdLine, cmdLine); +return true; +} + +/******************************************************************** +* RunNext/Run/RunProcess. +********************************************************************/ +void __cdecl call_thread(void * ptr){ + /* C++ adapter */ + ((CProcess *) ptr)->Run_Thread_Internal(); +} + +void CProcess::Run(void){ + // Check if something is already running before creating a thread. + if (!Running){ + // Call Run_Thread_Internal() + _beginthread(call_thread, 1024 * 1024, (void *) this); + } +} + +void CProcess::Run_Thread_Internal(void){ + exitCode = 0; + /* Execute each task */ + for ( ; ; ){ + /* If previous task returns an error code, abort */ + if (exitCode != 0) + break; + + // Get one task to execute. + currTask = Pop(); + + // Nothing to run. + if (!currTask) + break; + + /* Show command lines ?*/ + winApp.Report.Append(currTask->cmdLine, LVOUT_NORMAL); + + if (RunProcess(currTask)){ + winApp.Report.Append("Abort !", LVOUT_NORMAL); + exitCode = 1; + break; + } + } + + // Successful ? + if (exitCode == 0) + winApp.Report.Append("Performed successfully.", LVOUT_NORMAL); + + Flush(); + Running = false; +return; +} + +bool CProcess::RunProcess(CTask * task){ + if (!task) + return false; + + bool usePipes = task->creationFlag; + STARTUPINFO si = {sizeof(STARTUPINFO), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + + /* PROCESS_INFORMATION */ + pi.hProcess = 0; + pi.hThread = 0; + pi.dwProcessId = 0; + pi.dwThreadId = 0; + + /* Process creation with pipes */ + if (usePipes){ + /* Create needed pipes according to creationFlag */ + if(!Pipes.Create(task->creationFlag, winApp.isWinNT)){ + Pipes.CloseChildSide(); + Pipes.CloseParentSide(); + return false; + } + + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + //si.wShowWindow = SW_SHOWNORMAL; + + /* Set pipe handles */ + if (Pipes.hIn[1] != NULL && Pipes.hOut[1] != NULL){ + si.hStdInput = Pipes.hIn[1]; + si.hStdOutput = Pipes.hOut[1]; + if (Pipes.hErr[1] == NULL) + si.hStdError = Pipes.hOut[1]; + else + si.hStdError = Pipes.hErr[1]; + }else{ + sprintf(errmsg, "vm error: Process.cpp Invalid pipe handle"); + winApp.Report.Append(errmsg, LVOUT_ERROR); + Pipes.CloseChildSide(); + Pipes.CloseParentSide(); + return false; + } + } + + /* Create the child process */ + Running = CreateProcess(NULL, + task->cmdLine, + NULL, + NULL, + usePipes, + 0, + NULL, + /*startDir[0] ? startDir :*/ NULL, + &si, + &pi); + + if (!Running){ + /* CreateProcess failed. Close handles and return */ + Pipes.CloseChildSide(); + Pipes.CloseParentSide(); + sprintf(errmsg, "vm error: Process.cpp CreateProcess failed (e=%d)", (int)GetLastError()); + winApp.Report.Append(errmsg, LVOUT_ERROR); + return false; + }else{ + /* Close child process handles */ + Pipes.CloseChildSide(); + + if (!(usePipes & IN_PIPE)){ + /* Don't use the Input pipe */ + ::CloseHandle(Pipes.hIn[0]); + Pipes.hIn[0] = NULL; + } + } + + //sprintf(errmsg, "vm debug: enter io loop"); + //winApp.Report.Append(errmsg, LVOUT_ERROR); + if (usePipes){ + /* Initialize buffers */ + *outBuf = 0; + chr = outBuf; + bool bResult; + for ( ; ; ){ + Sleep(100L); + + bResult = ReadStdOut(task, Pipes.hOut[0]); + if (bResult != NO_ERROR) + break; + + ::GetExitCodeProcess(pi.hProcess, &exitCode); + if (exitCode != STILL_ACTIVE){ + break; + } + } + } + //sprintf(errmsg, "vm debug: exit io loop"); + //winApp.Report.Append(errmsg, LVOUT_ERROR); + + /* The child process is running. Perform I/O until terminated */ + ::WaitForSingleObject(pi.hProcess, INFINITE); + /* Process terminated. Get exit code. */ + ::GetExitCodeProcess(pi.hProcess, &exitCode); + if (exitCode == NO_ERROR){ + return NO_ERROR; + } + /* Close handles */ + Pipes.CloseParentSide(); + ::CloseHandle(pi.hProcess); + if (pi.hThread){ + ::CloseHandle(pi.hThread); + pi.hThread = NULL; + } +return exitCode; +} + +/******************************************************************** +* Pipes input/output. +********************************************************************/ +void CProcess::WriteStdIn(HANDLE hPipe, WORD){ + if (!hPipe) + return; + +return; +} + +void CProcess::ReadStdErr(HANDLE hPipe, WORD){ + if (!hPipe) + return; + +return; +} + +long CProcess::ReadStdOut(CTask * task, HANDLE hPipe){ + if (!task || !hPipe) + return ERROR_INVALID_FUNCTION; + + /* Copy each char and output lines while there is something to read */ + for ( ; ; ){ + // Copy one char, return if nothing available. + if (!ReadOneChar(hPipe, chr)) + break; + + // Ignore CR. + if (*chr == '\r') + continue; + + if (*chr != '\n'){ + chr++; + /* @@TODO Overflow + if ((chr - outBuf) >= max_len) + realloc(buffer);*/ + // End of line + }else if (*chr =='\n'){ + *chr = '\0'; + // Output error lines to List View. + if (task->outputFlag == STDOUT_FILE_APPEND){ + WriteFileAppend(task->szFileName, outBuf, (chr - outBuf)); + }else{ + OutputLine(task->outputFlag, outBuf, (chr - outBuf)); + } + *outBuf = '\0'; + chr = outBuf; + } + } +return NO_ERROR; +} + +int CProcess::ReadOneChar(HANDLE hPipe, char * chrin){ + DWORD bytesRead = 0; + DWORD bytesAvail = 0; + + if (!PeekNamedPipe(hPipe, chrin, (DWORD)1, &bytesRead, &bytesAvail, NULL)) + return 0; + + if (bytesAvail == 0) + return 0; + + if (!ReadFile(hPipe, chrin, (DWORD)1, &bytesRead, NULL)) + return 0; + +return bytesRead; +} + +bool CProcess::CommandLine(char * cmdLine){ + if (!Pipes.hIn[0]) + return false; + if (!Running || !currTask || !currTask->creationFlag) + return false; + int len = strlen(cmdLine); + if (len){ + strcpy(inBuf, cmdLine); + char * s = inBuf; + s+=len; + *s = '\r'; + s++; + *s = '\n'; + s++; + *s = '\0'; + } + DWORD written; + + if (!WriteFile(Pipes.hIn[0], inBuf, strlen(inBuf), &written, 0)) + return false; + +return true; +} + +bool CProcess::WriteFileAppend(char * fileName, char * line, int /*len*/){ + if (!*fileName) + return false; + + /* Append one line of text to a file */ + FILE * file = fopen(fileName, "a"); + if (file){ + fprintf(file, line); + fprintf(file, "\n"); + fclose(file); + return true; + } +return false; +} + +bool CProcess::OutputLine(WORD outputFlag, char * line, int /*len*/){ + /* Output error lines to List View */ + + CriticalSection.Enter(); + winApp.Report.Append(line, outputFlag); + CriticalSection.Leave(); +return true; +} + diff --git a/rosapps/devutils/vmingw/process.h b/rosapps/devutils/vmingw/process.h new file mode 100644 index 00000000000..f6bbaf01550 --- /dev/null +++ b/rosapps/devutils/vmingw/process.h @@ -0,0 +1,146 @@ +/******************************************************************** +* Module: process.h. This is part of Visual-MinGW. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#ifndef PROCESS_H +#define PROCESS_H +#include "winui.h" +#include "CList.h" + + +class CCommandDlg : public CDlgBase +{ + public: + CCommandDlg(); + ~CCommandDlg(); + + HWND Create(void); + LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + char cmdLine[1024]; + + protected: + + private: + HWND hCmdLine; +}; + +/******************************************************** + creationFlag truth table + ----------------------------------- + 8 4 2 1 + ------------------ + NO_PIPE 0 0 0 0 + IN_PIPE 0 0 0 1 + OUT_PIPE 0 0 1 0 + ERR_PIPE 0 1 0 0 + OUTERR_PIPE 1 0 1 0 + +*********************************************************/ +#define NO_PIPE 0x0000 +#define IN_PIPE 0x0001 +#define OUT_PIPE 0x0002 +#define ERR_PIPE 0x0004 +#define OUTERR_PIPE 0x000A + +#define STDOUT_NONE 0 +#define STDOUT_FILE_APPEND 1 +#define STDOUT_USER 2 + +class CTask : public CNode +{ + public: + CTask(); + ~CTask(); + + char cmdLine[MAX_PATH]; + char szFileName[MAX_PATH]; + WORD creationFlag; + WORD outputFlag; + + protected: + + private: + +}; + +class CStack : public CList +{ + public: + CStack(); + ~CStack(); + + int Push(CTask * newTask); + CTask * Pop(void); + void Flush(void); + + protected: + + private: + CTask * retBuf; + void DetachCurrent(void); +}; + +class CPipes +{ + public: + CPipes(); + ~CPipes(); + + HANDLE hIn[2]; + HANDLE hOut[2]; + HANDLE hErr[2]; + + bool Create(WORD creationFlag, bool winNT); + bool CloseChildSide(void); + bool CloseParentSide(void); + protected: + + private: + bool Close(int side); +}; + +class CProcess : public CStack +{ + public: + CProcess(); + ~CProcess(); + + bool CommandLine(char * cmdLine); + bool isRunning(void); + CTask * AddTask(char * cmdLine, WORD creationFlag, WORD outputFlag/* = STDOUT_NONE*/); + bool CmdCat(char * cmdLine); + void Run(void); + void Run_Thread_Internal(void); + + CCommandDlg CommandDlg; + protected: + + private: + PROCESS_INFORMATION pi; + bool Running; + DWORD exitCode; + CTask * currTask; + CPipes Pipes; + char * chr; + char inBuf[1024]; + char outBuf[1024]; + char errBuf[1024]; + + bool RunProcess(CTask * task); + + void WriteStdIn(HANDLE hPipe, WORD creationFlag); + void ReadStdErr(HANDLE hPipe, WORD creationFlag); + long ReadStdOut(CTask * task, HANDLE hPipe); + int ReadOneChar(HANDLE hPipe, char * chrin); + + bool WriteFileAppend(char * fileName, char * line, int len=-1); + bool OutputLine(WORD outputFlag, char * line, int len=-1); +}; + +#endif diff --git a/rosapps/devutils/vmingw/project.cpp b/rosapps/devutils/vmingw/project.cpp new file mode 100644 index 00000000000..2b0969f4d3d --- /dev/null +++ b/rosapps/devutils/vmingw/project.cpp @@ -0,0 +1,1453 @@ +/******************************************************************** +* Module: project.cpp. This is part of Visual-MinGW. +* +* Purpose: Procedures to manage a loaded project. +* +* Authors: Manu B. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +* Revisions: +* +********************************************************************/ +#include +#include + +#include "project.h" +#include "rsrc.h" + +extern CMessageBox MsgBox; + +// For dialogs. +extern CWinApp winApp; + +WORD AppendPath(char * dirBuffer, WORD offset, char * absolutePath); + +bool CheckFile(CFileItem * file){ + if (!file) + return false; + + char * fileName = file->szFileName; + char * s = fileName; + char * dot = fileName; + char * bkslash = fileName+1; + // Valid relative path ? + if (*dot == '.' && *bkslash == '\\'){ + s+=2; + // Find backslashes & dots. + while (*s != '\0'){ + if (*s == '\\'){ + bkslash = s; + }else if (*s == '.'){ + dot = s; + } + s++; + } + if (*bkslash != '\0'){ + file->nFileOffset = (bkslash - fileName) +1; + }else{ + file->nFileOffset = 0; + return false; + } + + if (dot != fileName) + file->nFileExtension = (dot - fileName) +1; + else + file->nFileExtension = 0; + return true; + } +return false; +} + +WORD AppendPath(char * dirBuffer, WORD offset, char * absolutePath){ + WORD len = 0; + if (absolutePath[0] == '.'){ + if (absolutePath[1] == '\\' && absolutePath[2] != '\0'){ + dirBuffer[offset-1] = '\\'; + strcpy(&dirBuffer[offset], &absolutePath[2]); + len = strlen(&dirBuffer[offset]); + len++; + } + } +return len; +} + + +/******************************************************************** +* Class: COptionsDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +COptionsDlg::COptionsDlg(){ + pProject = NULL; + pMakefile = NULL; +} + +COptionsDlg::~COptionsDlg(){ +} + +LRESULT CALLBACK COptionsDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_NOTIFY: + OnNotify((int) wParam, (LPNMHDR) lParam); + break; + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL COptionsDlg::OnInitDialog(HWND, LPARAM lInitParam){ + // Set pointers. + pProject = (CProject *) lInitParam; + if (pProject == NULL) + return TRUE; + + // Tab control handle and TCITEM. + _hWndTab = ::GetDlgItem(_hWnd, IDC_OPTION_TABS); + tcitem.mask = TCIF_TEXT | TCIF_PARAM; + + // Insert General tab. + HWND hwndChild = GeneralDlg.Create(this, IDD_GENERAL_PANE, NULL, (long) pProject); + tcitem.pszText = "General"; + tcitem.lParam = (long) &GeneralDlg; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 0, + (LPARAM)&tcitem); + SetChildPosition(hwndChild); + + // Insert Compiler tab item. + CompilerDlg.Create(this, IDD_COMPILER, &Pos, (long) pProject); + tcitem.pszText = "Compiler"; + tcitem.lParam = (long) &CompilerDlg; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 1, + (LPARAM)&tcitem); + + // Insert Linker tab. + LinkerDlg.Create(this, IDD_LINKER, &Pos, (long) pProject); + tcitem.pszText = "Linker"; + tcitem.lParam = (long) &LinkerDlg; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 2, + (LPARAM)&tcitem); + + // Insert Archives tab. + ZipDlg.Create(this, IDD_ZIP, &Pos, (long) pProject); + tcitem.pszText = "Archives"; + tcitem.lParam = (long) &ZipDlg; + ::SendMessage(_hWndTab, TCM_INSERTITEM, 3, + (LPARAM)&tcitem); + + // Show the dialog and default pane. + Show(); + GeneralDlg.Show(); + GeneralDlg.SetFocus(); +return TRUE; +} + +BOOL COptionsDlg::OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl){ + switch (wID){ + case IDOK: + GeneralDlg.OnCommand(wNotifyCode, wID, hwndCtl); + CompilerDlg.OnCommand(wNotifyCode, wID, hwndCtl); + LinkerDlg.OnCommand(wNotifyCode, wID, hwndCtl); + ZipDlg.OnCommand(wNotifyCode, wID, hwndCtl); + pProject->buildMakefile = true; + pProject->modified = true; + EndDlg(IDOK); + return TRUE; + + case IDCANCEL: + EndDlg(IDCANCEL); + break; + } +return 0; +} + +BOOL COptionsDlg::EndDlg(int nResult){ + GeneralDlg.EndDlg(0); + CompilerDlg.EndDlg(0); + LinkerDlg.EndDlg(0); + ZipDlg.EndDlg(0); + if (_hWnd){ + BOOL result = ::EndDialog(_hWnd, nResult); + _hWnd = 0; + return result; + } +return false; +} + + +/******************************************************************** +* Class: CGeneralDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CGeneralDlg::CGeneralDlg(){ + pProject = NULL; + pMakefile = NULL; +} + +CGeneralDlg::~CGeneralDlg(){ +} + +LRESULT CALLBACK CGeneralDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CGeneralDlg::OnInitDialog(HWND, LPARAM lInitParam){ + /* Set pointers */ + pProject = (CProject *) lInitParam; + if (pProject == NULL || &pProject->Makefile == NULL) + return TRUE; + pMakefile = &pProject->Makefile; + + /* Get control handles */ + hStatLib = GetItem(IDC_STATLIB); + hDll = GetItem(IDC_DLL); + hConsole = GetItem(IDC_CONSOLE); + hGuiExe = GetItem(IDC_GUIEXE); + hDbgSym = GetItem(IDC_DBGSYM); + hLangC = GetItem(IDC_LANGC); + hLangCpp = GetItem(IDC_LANGCPP); + hMkfName = GetItem(IDC_MKF_NAME); + hMkfDir = GetItem(IDC_MKF_DIR); + hUserMkf = GetItem(IDC_USER_MKF); + hTgtName = GetItem(IDC_TGT_NAME); + hTgtDir = GetItem(IDC_TGT_DIR); + + /* Set buttons state */ + switch(pMakefile->buildWhat){ + case BUILD_STATLIB: + ::SendMessage(hStatLib, BM_SETCHECK, BST_CHECKED, 0); + break; + case BUILD_DLL: + ::SendMessage(hDll, BM_SETCHECK, BST_CHECKED, 0); + break; + case BUILD_EXE: + ::SendMessage(hConsole, BM_SETCHECK, BST_CHECKED, 0); + break; + case BUILD_GUIEXE: + ::SendMessage(hGuiExe, BM_SETCHECK, BST_CHECKED, 0); + break; + } + if (pMakefile->debug) + ::SendMessage(hDbgSym, BM_SETCHECK, BST_CHECKED, 0); + + if (pMakefile->lang == LANGCPP) + ::SendMessage(hLangCpp, BM_SETCHECK, BST_CHECKED, 0); + else + ::SendMessage(hLangC, BM_SETCHECK, BST_CHECKED, 0); + + /* Set text */ + char name[64]; + if (pMakefile->nFileOffset){ + strcpy(name, &pMakefile->szFileName[pMakefile->nFileOffset]); + }else{ + strcpy(name, "noname"); + } + + SetItemText(hMkfName, name); + SetItemText(hMkfDir, pMakefile->mkfDir); + SetItemText(hTgtName, pMakefile->target); + SetItemText(hTgtDir, pMakefile->tgtDir); +return TRUE; +} + +BOOL CGeneralDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK:{ + /* Get text */ + char name[64]; + GetItemText(hMkfName, name, 64); + GetItemText(hMkfDir, pMakefile->mkfDir, MAX_PATH); + GetItemText(hTgtName, pMakefile->target, 64); + GetItemText(hTgtDir, pMakefile->tgtDir, MAX_PATH); + + pMakefile->GetFullPath(pMakefile->szFileName, pProject->nFileOffset, name); + //@@TODO check if directories exist. + + /* Get buttons state */ + char * pExt = strrchr(pMakefile->target, '.'); + if (!pExt){ + int len = strlen(pMakefile->target); + if (!len){ + strcpy(pMakefile->target, "noname"); + len = strlen(pMakefile->target); + } + pExt = pMakefile->target + len; + } + if (BST_CHECKED == ::SendMessage(hStatLib, BM_GETCHECK, 0, 0)){ + pMakefile->buildWhat = BUILD_STATLIB; + strcpy(pExt, ".a"); + }else if (BST_CHECKED == ::SendMessage(hDll, BM_GETCHECK, 0, 0)){ + pMakefile->buildWhat = BUILD_DLL; + strcpy(pExt, ".dll"); + }else if (BST_CHECKED == ::SendMessage(hConsole, BM_GETCHECK, 0, 0)){ + pMakefile->buildWhat = BUILD_EXE; + strcpy(pExt, ".exe"); + }else if (BST_CHECKED == ::SendMessage(hGuiExe, BM_GETCHECK, 0, 0)){ + pMakefile->buildWhat = BUILD_GUIEXE; + strcpy(pExt, ".exe"); + } + pMakefile->debug = + (BST_CHECKED==::SendMessage(hDbgSym, BM_GETCHECK, 0, 0)); + + if (BST_CHECKED == ::SendMessage(hLangCpp, BM_GETCHECK, 0, 0)){ + pMakefile->lang = LANGCPP; + strcpy(pMakefile->cc, "g++"); + }else{ + pMakefile->lang = LANGC; + strcpy(pMakefile->cc, "gcc"); + } + } + return TRUE; + + case IDCANCEL: + return FALSE; + } +return FALSE; +} + + +/******************************************************************** +* Class: CCompilerDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CCompilerDlg::CCompilerDlg(){ + pProject = NULL; + pMakefile = NULL; +} + +CCompilerDlg::~CCompilerDlg(){ +} + +LRESULT CALLBACK CCompilerDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CCompilerDlg::OnInitDialog(HWND, LPARAM lInitParam){ + // Set pointers. + pProject = (CProject *) lInitParam; + if (pProject == NULL || &pProject->Makefile == NULL) + return TRUE; + pMakefile = &pProject->Makefile; + + hCppFlags = GetItem(IDC_CPPFLAGS); + hWarning = GetItem(IDC_WARNING); + hOptimiz = GetItem(IDC_OPTIMIZ); + hCFlags = GetItem(IDC_CFLAGS); + hIncDirs = GetItem(IDC_INCDIRS); + + SetItemText(hCppFlags, pMakefile->cppFlags); + SetItemText(hWarning, pMakefile->warning); + SetItemText(hOptimiz, pMakefile->optimize); + SetItemText(hCFlags, pMakefile->cFlags); + SetItemText(hIncDirs, pMakefile->incDirs); +return TRUE; +} + +BOOL CCompilerDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + GetItemText(hCppFlags, pMakefile->cppFlags, 256); + GetItemText(hWarning, pMakefile->warning, 64); + GetItemText(hOptimiz, pMakefile->optimize, 64); + GetItemText(hCFlags, pMakefile->cFlags, 64); + GetItemText(hIncDirs, pMakefile->incDirs, 256); + return TRUE; + + case IDCANCEL: + return FALSE; + } +return FALSE; +} + + +/******************************************************************** +* Class: CLinkerDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CLinkerDlg::CLinkerDlg(){ + pProject = NULL; + pMakefile = NULL; +} + +CLinkerDlg::~CLinkerDlg(){ +} + +LRESULT CALLBACK CLinkerDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CLinkerDlg::OnInitDialog(HWND, LPARAM lInitParam){ + // Set pointers. + pProject = (CProject *) lInitParam; + if (pProject == NULL || &pProject->Makefile == NULL) + return TRUE; + pMakefile = &pProject->Makefile; + + hLdStrip = GetItem(IDC_LDSTRIP); + hLdOpts = GetItem(IDC_LDOPTS); + hLdLibs = GetItem(IDC_LDLIBS); + hLibsDirs = GetItem(IDC_LIBDIRS); + + SetItemText(hLdStrip, pMakefile->ldStrip); + SetItemText(hLdOpts, pMakefile->ldOpts); + SetItemText(hLdLibs, pMakefile->ldLibs); + SetItemText(hLibsDirs, pMakefile->libDirs); +return TRUE; +} + +BOOL CLinkerDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + GetItemText(hLdStrip, pMakefile->ldStrip, 32); + GetItemText(hLdOpts, pMakefile->ldOpts, 64); + GetItemText(hLdLibs, pMakefile->ldLibs, 64); + GetItemText(hLibsDirs, pMakefile->libDirs, 256); + return TRUE; + + case IDCANCEL: + return FALSE; + } +return FALSE; +} + + +/******************************************************************** +* Class: CZipDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CZipDlg::CZipDlg(){ + pProject = NULL; + pMakefile = NULL; +} + +CZipDlg::~CZipDlg(){ +} + +LRESULT CALLBACK CZipDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + switch(Message){ + case WM_INITDIALOG: + return OnInitDialog((HWND) wParam, lParam); + + case WM_COMMAND: + OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + +BOOL CZipDlg::OnInitDialog(HWND, LPARAM lInitParam){ + // Set pointers. + pProject = (CProject *) lInitParam; + if (pProject == NULL || &pProject->Makefile == NULL) + return TRUE; + pMakefile = &pProject->Makefile; + + hZipDir = GetItem(IDC_ZIP_DIR); + hZipFlags = GetItem(IDC_ZIPFLAGS); + SetItemText(hZipDir, pProject->zipDir); + SetItemText(hZipFlags, pProject->zipFlags); +return TRUE; +} + +BOOL CZipDlg::OnCommand(WORD, WORD wID, HWND){ + switch (wID){ + case IDOK: + GetItemText(hZipDir, pProject->zipDir, MAX_PATH); + GetItemText(hZipFlags, pProject->zipFlags, 256); + return TRUE; + + case IDCANCEL: + return FALSE; + } +return FALSE; +} + + +/******************************************************************** +* Class: CNewModuleDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CNewModuleDlg::CNewModuleDlg(){ + pProject = NULL; +} + +CNewModuleDlg::~CNewModuleDlg(){ +} + +LRESULT CALLBACK CNewModuleDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ + + char fileName[64]; + bool createHeader = true; + HWND wCreateHeader = GetItem(IDC_HEADER); + + switch(Message){ + case WM_INITDIALOG: + pProject = (CProject *) lParam; + if (createHeader) + ::SendMessage(wCreateHeader, BM_SETCHECK, BST_CHECKED, 0); + strcpy(fileName, "new.cpp"); + ::SetDlgItemText(_hWnd, 301, fileName); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDCANCEL){ + fileName[0] = 0; + EndDlg(IDCANCEL); + return FALSE; + }else if(LOWORD(wParam) == IDOK){ + ::GetDlgItemText(_hWnd, 301, fileName, 64); + createHeader = BST_CHECKED == + ::SendMessage(wCreateHeader, BM_GETCHECK, 0, 0); + pProject->NewModule(fileName, createHeader); + EndDlg(IDCANCEL); + return TRUE; + } + break; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + + +/******************************************************************** +* Class: CProject. +* +* Purpose: Project management. +* +* Revisions: +* +********************************************************************/ +//@@TODO close project Dlg's before closing Project. +CProject::CProject(){ + prjVer = 40; +} + +CProject::~CProject(){ +} + +void CProject::Reset(){ + szFileName[MAX_PATH - 1] = '\0'; // security. + szFileName[0] = '\0'; + szDirBuffer[0] = '\0'; + nFileOffset = 0; + nFileExtension = 0; + + strcpy (zipDir, "."); + strcpy (zipFlags, "*.*"); + numFiles = 0; + loaded = false; + modified = false; + buildMakefile = true; + + compilerName[0] = '\0'; + + Makefile.Init(); +} + +bool CProject::NoProject(void){ + if (!loaded){ + MsgBox.DisplayWarning("No project loaded"); + // Or directly show open project dlg. + return true; + } +return false; +} + +int CProject::CloseDecision(void){ + if (loaded){ + return MsgBox.Ask("Close current project ?", false); + } +return IDNO; +} + +bool CProject::SwitchCurrentDir(void){ + // Switch to Project Directory + szDirBuffer[nFileOffset-1] = '\0'; +return ::SetCurrentDirectory(szDirBuffer); +} + +bool CProject::RelativeToAbsolute(char * relativePath){ + if (*szDirBuffer && nFileOffset){ + if (relativePath[0] == '.' && relativePath[1] == '\\' + && relativePath[2] != '\0'){ + szDirBuffer[nFileOffset-1] = '\\'; + strcpy(&szDirBuffer[nFileOffset], &relativePath[2]); + return true; + } + } +return false; +} + + +/******************************************************************** +* New Project. +********************************************************************/ +bool CProject::New(char * fileName, WORD fileOffset){ + // Load default values. + Reset(); + + // Copy project file's directory. + strcpy(szFileName, fileName); + nFileOffset = fileOffset; + + strncpy(szDirBuffer, szFileName, (nFileOffset - 1)); + szDirBuffer[nFileOffset-1] = '\0'; + strcpy(winApp.projectDir, szDirBuffer); + + // Makefile: Get target name. + nFileExtension = winApp.FileDlg.GetFileExtension(); + strcpy(Makefile.target, &szFileName[nFileOffset]); + char * pExt = strrchr(Makefile.target, '.'); + if (pExt){ + *pExt='\0'; + } + loaded = true; + + AddFiles(); + + Makefile.GetFullPath(szFileName, nFileOffset, "makefile"); + + buildMakefile = true; + OptionsDlg(); + SavePrjFile(IDYES); +return true; +} + +/******************************************************************** +* Open Project. +********************************************************************/ +bool CProject::Open(char * fileName, WORD fileOffset){ + // Initialize project tree view. + Reset(); + + // Copy project file's directory. + strcpy(szFileName, fileName); + nFileOffset = fileOffset; + + strncpy(szDirBuffer, szFileName, (nFileOffset - 1)); + szDirBuffer[nFileOffset-1] = '\0'; + strcpy(winApp.projectDir, szDirBuffer); + + // Load project file in a buffer. + if (!PrjFile.Load(szFileName)){ + MsgBox.DisplayFatal("Can't load project file !"); + //@@ should close inifile ? + return false; + } + + char name[64]; + *name = '\0'; + // [Project] section + int signature = PrjFile.GetInt( "Signature", "Project" ); + if (signature != prjVer){ + MsgBox.DisplayFatal("Bad signature in the project file !"); + return false; + } + + numFiles = PrjFile.GetInt( "NumFiles" ); + PrjFile.GetString(compilerName, "Compiler" ); + buildMakefile = PrjFile.GetInt( "BuildMakefile" ); + + // [Archives] section + PrjFile.GetString(zipDir, "Directory", "Archives" ); + PrjFile.GetString(zipFlags, "Flags"); + + // [Makefile] section + PrjFile.GetString(Makefile.make, "Make", "Makefile" ); + PrjFile.GetString(Makefile.cc, "CC" ); + PrjFile.GetString(Makefile.wres, "WRES" ); + PrjFile.GetString(Makefile.test, "TEST" ); + PrjFile.GetString(name, "Makefile" ); + PrjFile.GetString(Makefile.mkfDir, "MakefileDir"); + PrjFile.GetString(Makefile.target, "Target" ); + PrjFile.GetString(Makefile.tgtDir, "TargetDir" ); + Makefile.buildWhat = PrjFile.GetInt( "Build" ); + Makefile.debug = PrjFile.GetInt( "Debug" ); + Makefile.lang = PrjFile.GetInt( "Lang" ); + PrjFile.GetString(Makefile.cppFlags, "CppFlags" ); + PrjFile.GetString(Makefile.warning, "CcWarning"); + PrjFile.GetString(Makefile.optimize, "CcOptimize"); + PrjFile.GetString(Makefile.cFlags, "CcFlags" ); + PrjFile.GetString(Makefile.incDirs, "IncDirs" ); + PrjFile.GetString(Makefile.ldStrip, "LdStrip" ); + PrjFile.GetString(Makefile.ldOpts, "LdOptions" ); + PrjFile.GetString(Makefile.ldLibs, "LdLibraries"); + PrjFile.GetString(Makefile.libDirs, "LdLibDirs" ); + + Makefile.GetFullPath(szFileName, nFileOffset, name); + + if (numFiles){ + CFileItem * srcFile; + // [FileXX] section + char fileNumber [8]; + char fileSection [16]; + + for (int n=1; n<=numFiles; n++){ + itoa(n, fileNumber, 10); + strcpy(fileSection, "File"); + strcat(fileSection, fileNumber); + + // SrcFile + srcFile = new CFileItem; + srcFile->isInProject = true; + PrjFile.GetString(srcFile->szFileName, "Name", fileSection); + CheckFile(srcFile); + ::GetFileType(srcFile); + srcFile->show = PrjFile.GetInt( "Show" ); + + if(!winApp.Manager.OpenFile(srcFile)){ + delete srcFile; + return false; + } + } + } + loaded = true; +return true; +} + +int CProject::SavePrjFile(int decision){ + if (!loaded || !modified) + return decision; + if (decision == IDNO || decision == IDCANCEL) + return decision; + + /* Ask ? */ + if (decision == IDASK){ + decision = MsgBox.AskToSave(true); // Cancel button. + if (decision != IDYES) + return decision; // IDNO or IDCANCEL. + } + + CProjectView * pProjectView = &winApp.Manager.ProjectView; + FILE * file; + CFileItem * srcFile; + int count = 0; + + numFiles = pProjectView->Length(); + + file = fopen(szFileName, "w"); + if (!file){ + MsgBox.DisplayFatal("Can't save project file !"); + return decision; + } + + // [Project] + fprintf (file, "[Project]\nSignature = %d" , prjVer ); + fprintf (file, "\nNumFiles = %d" , numFiles ); + fprintf (file, "\nCompiler = %s" , compilerName ); + fprintf (file, "\nBuildMakefile = %d" , buildMakefile ); + + // [Archives] + fprintf (file, "\n\n[Archives]\nDirectory = %s" , zipDir ); + fprintf (file, "\nFlags = %s" , zipFlags ); + + // [Makefile] + fprintf (file, "\n\n[Makefile]\nMAKE = %s" , Makefile.make ); + fprintf (file, "\nCC = %s" , Makefile.cc ); + fprintf (file, "\nWRES = %s" , Makefile.wres ); + fprintf (file, "\nTEST = %s" , Makefile.test ); + fprintf (file, "\nMakefile = %s" , &Makefile.szFileName[Makefile.nFileOffset]); + fprintf (file, "\nMakefileDir = %s" , Makefile.mkfDir ); + fprintf (file, "\nTarget = %s" , Makefile.target ); + fprintf (file, "\nTargetDir = %s" , Makefile.tgtDir ); + fprintf (file, "\nBuild = %d" , Makefile.buildWhat ); + fprintf (file, "\nDebug = %d" , Makefile.debug ); + fprintf (file, "\nLang = %d" , Makefile.lang ); + fprintf (file, "\nCppFlags = %s" , Makefile.cppFlags ); + fprintf (file, "\nCcWarning = %s" , Makefile.warning ); + fprintf (file, "\nCcOptimize = %s" , Makefile.optimize ); + fprintf (file, "\nCcFlags = %s" , Makefile.cFlags ); + fprintf (file, "\nIncDirs = %s" , Makefile.incDirs ); + fprintf (file, "\nLdStrip = %s" , Makefile.ldStrip ); + fprintf (file, "\nLdOptions = %s" , Makefile.ldOpts ); + fprintf (file, "\nLdLibraries = %s" , Makefile.ldLibs ); + fprintf (file, "\nLdLibDirs = %s" , Makefile.libDirs ); + + /* [Filexx] */ + srcFile = (CFileItem *) pProjectView->First(); + while (srcFile){ + count++; + fprintf (file, "\n\n[File%d" , count ); + fprintf (file, "]\nName = %s" , srcFile->szFileName ); + fprintf (file, "\nShow = %d" , 0 ); + srcFile = (CFileItem *) pProjectView->Next(); + } + fprintf (file, "\n"); + fclose(file); + modified = false; +return decision; +} + +bool CProject::NewModule(char * name, bool createHeader){ + if (NoProject()) + return false; + + SwitchCurrentDir(); + + CFileItem * srcFile = winApp.Manager.ProjectView.NewFile(name); + if (!srcFile){ + MsgBox.DisplayWarning("Can't create file : %s", name); + return false; + } + if (createHeader && srcFile->type != H_FILE){ + char header[64]; + strcpy(header, name); + char ext[] = "h"; + ChangeFileExt(header, ext); + + if (!winApp.Manager.ProjectView.NewFile(header)){ + MsgBox.DisplayWarning("Can't create file : %s", header); + return false; + } + } +return true; +} + +bool CProject::AddFiles(void){ + if (NoProject()) + return false; + + CFileItem * srcFile; + char srcFiles[2048]; + srcFiles [0] = 0; + WORD fileOffset; + + // Show Open dialog. + if (!winApp.FileDlg.Open(&winApp, srcFiles, 2048, ADD_SRC_FILE)) + return false; // canceled by user + + // Check if srcFiles path includes projectDir. + int n = 0; + int maxlen = nFileOffset - 1; + while (n 2){ + relativePath[nn] = '\\'; + nn++; + } + relativePath[nn] = '\0'; + + // Append each file name. + fileOffset = winApp.FileDlg.GetFileOffset(); + + while (fileOffset){ + // Try to add each file to the project. + srcFile = new CFileItem; + strcpy(srcFile->szFileName, relativePath); + + strcat(srcFile->szFileName, &srcFiles[fileOffset]); + + CheckFile(srcFile); + ::GetFileType(srcFile); + srcFile->show = 0; + srcFile->isInProject = true; + + if(!winApp.Manager.ProjectView.OpenFile(srcFile)){ + delete srcFile; + return false; + } + + fileOffset = winApp.FileDlg.GetNextFileOffset(); + } + modified = true; + buildMakefile = true; + return true; + } + MsgBox.DisplayString("Out of the project"); +return false; +} + +/******************************************************************** +* Dialogs. +********************************************************************/ +bool CProject::OptionsDlg(void){ +/**/ if (NoProject()) + return false; + + _OptionsDlg.CreateModal(&winApp, IDD_OPTION, (LPARAM) this); +return true; +} + +bool CProject::NewModuleDlg(void){ + if (NoProject()) + return false; + + _NewModuleDlg.CreateModal(&winApp, IDD_NEW_MODULE, (LPARAM) this); +return true; +} + +/******************************************************************** +* Project Commands. +********************************************************************/ +void CProject::ZipSrcs(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + // Switch to Project Directory + SwitchCurrentDir(); + + winApp.Report.Clear(); + + char fileName[64]; + char date[16]; + date[0] = 0; + + // Archive name = zipDir\month+day+year+src.zip + GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, "MMddyyyy", + date, 16); + + if (*zipDir == '\0') + strcpy (zipDir, "."); + strcpy (fileName, zipDir); + strcat (fileName, "\\"); + strcat (fileName, date); + strcat (fileName, "src"); + strcat (fileName, ".zip"); + + char msgBuf[128]; + sprintf(msgBuf, "Create archive > %s", fileName); + winApp.Report.Append(msgBuf, LVOUT_NORMAL); + + // Put the command line and the run flag in the command stack. + winApp.Process.AddTask( + "zip ", + OUTERR_PIPE, + LVOUT_NORMAL); + + winApp.Process.CmdCat(fileName); + if (*zipFlags){ + winApp.Process.CmdCat(" "); + winApp.Process.CmdCat(zipFlags); + } + + winApp.Process.Run(); +} + +void CProject::Explore(HWND hwnd){ + if (NoProject()) + return; + + if(ShellExecute(hwnd, "explore", szDirBuffer, NULL, NULL, SW_SHOWMAXIMIZED) + < (HINSTANCE) 32){ + MsgBox.DisplayString("Can't launch Explorer"); + return; + } +} + +/******************************************************************** +* Compiler Commands. +********************************************************************/ +void CProject::Build(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + winApp.Report.Clear(); + winApp.Report.Append("Invoking compiler...", LVOUT_NORMAL); + + // Save modified files + winApp.Manager.ProjectView.SaveAll(IDYES); // Silent. + + // Switch to Makefile Directory + Makefile.SwitchCurrentDir(); + + /* Build makefile ? */ + if (buildMakefile){ + winApp.Report.Append("Building makefile...", LVOUT_NORMAL); + + // Fill buffers and initialize a new process. + Makefile.Build(&winApp.Manager.ProjectView, &winApp.Process); + buildMakefile = false; + modified = true; + } + + // Put the command line and the run flag in the command stack. + winApp.Process.AddTask( + Makefile.make, + OUTERR_PIPE, + LVOUT_ERROR); + + winApp.Process.CmdCat(" -f "); + winApp.Process.CmdCat(&Makefile.szFileName[Makefile.nFileOffset]); + if (Makefile.debug) + winApp.Process.CmdCat(" debug"); + + winApp.Process.Run(); +} + +void CProject::RebuildAll(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + // Switch to Makefile Directory + Makefile.SwitchCurrentDir(); + + winApp.Report.Clear(); + winApp.Report.Append("Invoking compiler...", LVOUT_NORMAL); + + // Save modified files + winApp.Manager.ProjectView.SaveAll(IDYES); // Silent. + + // Build makefile. + Makefile.Build(&winApp.Manager.ProjectView, &winApp.Process); + buildMakefile = false; + modified = true; + + // Make clean. + winApp.Process.AddTask( + Makefile.make, + OUTERR_PIPE, + LVOUT_ERROR); + + winApp.Process.CmdCat(" -f "); + winApp.Process.CmdCat(&Makefile.szFileName[Makefile.nFileOffset]); + winApp.Process.CmdCat(" clean"); + + // Build. + winApp.Process.AddTask( + Makefile.make, + OUTERR_PIPE, + LVOUT_ERROR); + + winApp.Process.CmdCat(" -f "); + winApp.Process.CmdCat(&Makefile.szFileName[Makefile.nFileOffset]); + if (Makefile.debug) + winApp.Process.CmdCat(" debug"); + + winApp.Process.Run(); +} + +void CProject::RunTarget(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + if (Makefile.buildWhat == BUILD_STATLIB + || Makefile.buildWhat ==BUILD_DLL) + return; + + winApp.Report.Clear(); + winApp.Report.Append("Run target...", LVOUT_NORMAL); + + // Put the command line and the run flag in the command stack. + winApp.Process.AddTask(szDirBuffer, NO_PIPE, STDOUT_NONE); + winApp.Process.CmdCat("\\"); + if (Makefile.tgtDir[0] == '.'){ + if (Makefile.tgtDir[1] == '.' && Makefile.tgtDir[2] == '\\' + && Makefile.tgtDir[3] != '\0'){ + winApp.Process.CmdCat(&Makefile.tgtDir[3]); + }else{ + // Invalid dir, try ".\target". + winApp.Process.CmdCat("."); + } + } + winApp.Process.CmdCat("\\"); + winApp.Process.CmdCat(Makefile.target); + + winApp.Process.Run(); +} + +void CProject::MakeClean(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + // Switch to Makefile Directory + Makefile.SwitchCurrentDir(); + + winApp.Report.Clear(); + winApp.Report.Append("Deleting objects...", LVOUT_NORMAL); + + // Put the command line and the output flag in the command stack. + winApp.Process.AddTask( + Makefile.make, + OUTERR_PIPE, + LVOUT_ERROR); + + winApp.Process.CmdCat(" -f "); + winApp.Process.CmdCat(&Makefile.szFileName[Makefile.nFileOffset]); + winApp.Process.CmdCat(" clean"); + + winApp.Process.Run(); +} + +void CProject::BuildMakefile(void){ + if (NoProject() || winApp.Process.isRunning()) + return; + + // Switch to Project Directory + Makefile.SwitchCurrentDir(); + + winApp.Report.Clear(); + winApp.Report.Append("Building makefile...", LVOUT_NORMAL); + + // Fill buffers and initialize a new process. + Makefile.Build(&winApp.Manager.ProjectView, &winApp.Process); + buildMakefile = false; + modified = true; + // Run the process. + winApp.Process.Run(); +} + + +/******************************************************************** +* Class: CMakefile. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CMakefile::CMakefile(){ + Init(); +} + +CMakefile::~CMakefile(){ +} + +void CMakefile::Init(void){ + szFileName[MAX_PATH - 1] = '\0'; // security. + szFileName[0] = '\0'; + nFileOffset = 0; + strcpy (mkfDir, "."); + + strcpy (cc, "gcc"); + strcpy (make, "make"); + strcpy (wres, "windres"); + strcpy (test, "gcc -v"); + + target[0] = '\0'; + strcpy (tgtDir, "."); + buildWhat = BUILD_EXE; + debug = false; + lang = LANGC; + + cppFlags[0] = '\0'; + strcpy (warning, "-W -Wall -pedantic"); + strcpy (optimize, "-O2"); + cFlags[0] = '\0'; + incDirs[0] = '\0'; + + strcpy (ldStrip, "-s"); + ldOpts[0] = '\0'; + ldLibs[0] = '\0'; + libDirs[0] = '\0'; + *arFlags = '\0'; +} + +void CMakefile::GetFullPath(char * prjFileName, WORD offset, char * name){ + // Copy project directory and append makefile relative dir. + strncpy(szFileName, prjFileName, offset); + WORD len = AppendPath(szFileName, offset, mkfDir); + // Increment file offset. + if (len){ + offset += len; + }else{ + strcpy(mkfDir, "."); + } + // Append makefile name. + szFileName[offset-1] = '\\'; + if (*name){ + strcpy(&szFileName[offset], name); + }else{ + strcpy(name, "makefile"); + } + nFileOffset = offset; +} + +bool CMakefile::SwitchCurrentDir(void){ + // Switch to Makefile Directory. + if (nFileOffset < 2) + return false; + szFileName[nFileOffset-1] = '\0'; + bool result = SetCurrentDirectory(szFileName); + szFileName[nFileOffset-1] = '\\'; +return result; +} + +void CMakefile::Build(CProjectView * Tree, CProcess* /*Process*/){ + SrcList2Buffers(Tree); + // Write the first part of the Makefile. + Write(); + + /* Invokes compiler to get dependencies with something like: + "gcc -MM file1.cpp file2.cpp ..." */ + + CTask * task = winApp.Process.AddTask( + depBuf, + OUTERR_PIPE, + STDOUT_FILE_APPEND); + strcpy(task->szFileName, szFileName); +} + +void CMakefile::SrcList2Buffers(CProjectView * Tree){ + + // 1. Begin to fill each buffer. + strcpy(depBuf, cc); + if (*cppFlags != '\0'){ + strcat(depBuf, " "); + strcat(depBuf, cppFlags); + } + strcat(depBuf, " -MM "); + if (*incDirs != '\0'){ + strcat(depBuf, incDirs); + strcat(depBuf, " "); + } + + strcpy(srcBuf, "\nSRCS\t=\\\n"); + strcpy(objBuf, "\nOBJS\t=\\\n"); + resBuf [0] = 0; + + // 2. Parse the module list and retrieve sources files names. + CFileItem* srcFile; + + if(!Tree->First()) + return; // The list is empty, nothing to search. + + do { srcFile = (CFileItem *) Tree->GetCurrent(); + + if (srcFile->type == C_FILE || srcFile->type == RC_FILE){ + // Source files and objects buffers. + strcat (srcBuf, "\t"); + strcat (srcBuf, &srcFile->szFileName[srcFile->nFileOffset]); + strcat (srcBuf, "\\\n"); + + // Change file extension. + char ext[] = "o"; + strcpy(objFile, &srcFile->szFileName[srcFile->nFileOffset]); + ChangeFileExt(objFile, ext); + strcat (objBuf, "\t"); + strcat (objBuf, objFile); + strcat (objBuf, "\\\n"); + + if (srcFile->type == C_FILE){ + // Dependencies buffer. + strcat(depBuf, &srcFile->szFileName[srcFile->nFileOffset]); + strcat(depBuf, " "); + }else if (srcFile->type == RC_FILE){ + // Resource buffer. + strcat (resBuf, objFile); + strcat (resBuf, ": "); + strcat (resBuf, &srcFile->szFileName[srcFile->nFileOffset]); + strcat (resBuf, "\n\n"); + } + } + } while (Tree->Next()); + + int len = strlen(srcBuf); + srcBuf[len-2] = '\n'; + srcBuf[len-1] = 0; + + len = strlen(objBuf); + objBuf[len-2] = '\n'; + objBuf[len-1] = 0; +} + +void CMakefile::Write(void){ + FILE * file; + + file = fopen(szFileName, "w"); + if (!file){ + MsgBox.DisplayString("Can't open file :\r\n%s", szFileName); + return; + } + + /* Signature */ + fprintf (file, "# Generated automatically by Visual-MinGW.\n"); + fprintf (file, "# http://visual-mingw.sourceforge.net/\n"); + + /* Standard defines */ + fprintf (file, "\nCC = %s", cc); + fprintf (file, "\nWRES = %s", wres ); + fprintf (file, "\nDLLWRAP = dllwrap" ); + fprintf (file, "\nCPPFLAGS = %s", cppFlags ); + + if (buildWhat == BUILD_GUIEXE) + fprintf (file, "\nLDBASEFLAGS = -mwindows %s %s", ldOpts, ldLibs ); + else + fprintf (file, "\nLDBASEFLAGS = %s %s", ldOpts, ldLibs ); + fprintf (file, "\nINCDIRS = %s", incDirs ); + fprintf (file, "\nOPTIMIZ = %s", optimize ); + fprintf (file, "\nSTRIP = %s", ldStrip ); + /* Debug symbols ? Language ? */ + fprintf (file, "\n\nifeq ($(MAKECMDGOALS),debug)"); + if (lang == LANGCPP){ + fprintf (file, "\nCXXFLAGS = %s $(INCDIRS) -g %s", warning, cFlags); + fprintf (file, "\nLDFLAGS = $(LDBASEFLAGS)"); + fprintf (file, "\nelse"); + fprintf (file, "\nCXXFLAGS = %s $(INCDIRS) $(OPTIMIZ) %s", warning, cFlags); + fprintf (file, "\nLDFLAGS = $(STRIP) $(LDBASEFLAGS)"); + fprintf (file, "\nendif"); + }else{ + fprintf (file, "\nCFLAGS = %s $(INCDIRS) -g %s", warning, cFlags); + fprintf (file, "\nLDFLAGS = $(LDBASEFLAGS)"); + fprintf (file, "\nelse"); + fprintf (file, "\nCFLAGS = %s $(INCDIRS) $(OPTIMIZ) %s", warning, cFlags); + fprintf (file, "\nLDFLAGS = $(STRIP) $(LDBASEFLAGS)"); + fprintf (file, "\nendif"); + } + /* Directories */ + fprintf (file, "\n\nSRCDIR = %s", mkfDir ); + fprintf (file, "\nBINDIR = %s", tgtDir ); + fprintf (file, "\nLIBDIRS = %s", libDirs ); + /* Rule to compile rc files */ + fprintf (file, "\n\n%c.o : %c.rc\n\t$(WRES) $(CPPFLAGS) $< $@", '%', '%' ); + /* List of objects */ + fprintf (file, "\n%s", objBuf ); + /* Target */ + fprintf (file, "\nTARGET =\t$(BINDIR)\\%s" , target ); + /* all, alldebug */ + fprintf (file, "\n\n# Targets\n" ); + fprintf (file, "all:\t$(TARGET)\n\ndebug:\t$(TARGET)\n\n" ); + /* clean */ + fprintf (file, "cleanobjs:\n\trm -f $(OBJS)\n\n" ); + fprintf (file, "cleanbin:\n\trm -f $(TARGET)\n\n" ); + fprintf (file, "clean:\tcleanobjs cleanbin\n\n" ); + /* Dependencies */ + fprintf (file, "# Dependency rules\n" ); + /* Language */ + if (buildWhat == BUILD_STATLIB){ + fprintf (file, "$(TARGET): $(OBJS)\n\t$(AR) -ru $(BINDIR)\\%s", target); + fprintf (file, " $(OBJS) $(INCDIRS) $(LIBDIRS)\n\n%s", resBuf); + }else if (buildWhat == BUILD_DLL){ + fprintf (file, "$(TARGET): $(OBJS)\n\t$(DLLWRAP) -o $@ $(OBJS) $(LDFLAGS)\n\n" ); + }else if (lang == LANGCPP){ + fprintf (file, "$(TARGET): $(OBJS)\n\t$(CXX) -o $(BINDIR)\\%s", target); + fprintf (file, " $(OBJS) $(INCDIRS) $(LIBDIRS) $(LDFLAGS)\n\n%s",resBuf); + }else{ + fprintf (file, "$(TARGET): $(OBJS)\n\t$(CC) -o $(BINDIR)\\%s", target); + fprintf (file, " $(OBJS) $(INCDIRS) $(LIBDIRS) $(LDFLAGS)\n\n%s",resBuf); + } + fclose(file); +} + + +/******************************************************************** +* Class: CCompiler. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CCompiler::CCompiler(){ + make[0] = '\0'; + cc[0] = '\0'; + cFlags[0] = '\0'; + ldFlags[0] = '\0'; + wres[0] = '\0'; + debug[0] = '\0'; + test[0] = '\0'; +} + +CCompiler::~CCompiler(){ +} + +bool CCompiler::LoadData(char * fullpath){ + Load(fullpath); + // [Common] section + GetString(make, "MAKE", "Common"); + GetString(cc, "CC" ); + GetString(cFlags, "CFLAGS" ); + GetString(ldFlags, "LDFLAGS" ); + GetString(wres, "WRES" ); + GetString(debug, "DEBUG" ); + GetString(test, "TEST" ); +return true; +} + diff --git a/rosapps/devutils/vmingw/project.h b/rosapps/devutils/vmingw/project.h new file mode 100644 index 00000000000..8441579576f --- /dev/null +++ b/rosapps/devutils/vmingw/project.h @@ -0,0 +1,295 @@ +/******************************************************************** +* Module: project.h. This is part of Visual-MinGW. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#ifndef PROJECT_H +#define PROJECT_H + +#include "winui.h" +#include "main.h" +#include "process.h" + +#define BUILD_STATLIB 0 +#define BUILD_DLL 1 +#define BUILD_EXE 2 +#define BUILD_GUIEXE 3 +#define LANGC 0 +#define LANGCPP 1 + +class CProject; +class CMakefile; + +bool CheckFile(CFileItem * file); + +class CGeneralDlg : public CDlgBase +{ + public: + CGeneralDlg(); + virtual ~CGeneralDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CProject *pProject; + CMakefile *pMakefile; + HWND hStatLib; + HWND hDll; + HWND hConsole; + HWND hGuiExe; + HWND hDbgSym; + HWND hLangC; + HWND hLangCpp; + HWND hMkfName; + HWND hMkfDir; + HWND hUserMkf; + HWND hTgtName; + HWND hTgtDir; +}; + +class CCompilerDlg : public CDlgBase +{ + public: + CCompilerDlg(); + virtual ~CCompilerDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CProject *pProject; + CMakefile *pMakefile; + HWND hCppFlags; + HWND hWarning; + HWND hOptimiz; + HWND hCFlags; + HWND hIncDirs; +}; + +class CZipDlg : public CDlgBase +{ + public: + CZipDlg(); + virtual ~CZipDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CProject *pProject; + CMakefile *pMakefile; + HWND hZipDir; + HWND hZipFlags; +}; + +class CLinkerDlg : public CDlgBase +{ + public: + CLinkerDlg(); + virtual ~CLinkerDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CProject *pProject; + CMakefile *pMakefile; + HWND hLdStrip; + HWND hLdOpts; + HWND hLdLibs; + HWND hLibsDirs; +}; + +class COptionsDlg : public CTabbedDlg +{ + public: + COptionsDlg(); + virtual ~COptionsDlg(); + + BOOL EndDlg(int nResult); + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + BOOL OnInitDialog(HWND hwndFocus, LPARAM lInitParam); + BOOL OnCommand(WORD wNotifyCode, WORD wID, HWND hwndCtl); + + protected: + + private: + CProject *pProject; + CMakefile *pMakefile; + CGeneralDlg GeneralDlg; + CCompilerDlg CompilerDlg; + CLinkerDlg LinkerDlg; + CZipDlg ZipDlg; +}; + +class CNewModuleDlg : public CDlgBase +{ + public: + CNewModuleDlg(); + virtual ~CNewModuleDlg(); + + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + + protected: + + private: + CProject *pProject; +}; + +class CCompiler : public CIniFile +{ + public: + CCompiler(); + ~CCompiler(); + + bool LoadData(char * fullpath); + + char make[64]; + + char cc[16]; + char cFlags[64]; + char ldFlags[64]; + char wres[16]; + + char debug[16]; + char test[16]; + + protected: + + private: +}; + +class CMakefile +{ + public: + CMakefile(); + ~CMakefile(); + + void Init(void); + bool SwitchCurrentDir(void); + void GetFullPath(char * prjFileName, WORD offset, char * name); + void Build(CProjectView * Tree, CProcess* Process); + void SrcList2Buffers(CProjectView * Tree); + void Write(void); + + // File. + char szFileName[MAX_PATH]; + WORD nFileOffset; + char mkfDir[MAX_PATH]; + + // Compiler dependent. + char cc[4]; + char make[64]; + char wres[16]; + char test[16]; + + char target[64]; + char tgtDir[MAX_PATH]; + UINT buildWhat; + bool debug; + UINT lang; + + // Compiler data. + char cppFlags[256]; + char warning[64]; + char optimize[64]; + char cFlags[64]; + char incDirs[256]; + + // Linker data. + char ldStrip[32]; + char ldOpts[64]; + char ldLibs[64]; + char libDirs[256]; + + // Archiver. + char arFlags[64]; + + protected: + + private: + // Buffers. + char objFile[64]; + char srcBuf [1024]; + char objBuf [1024]; + char resBuf [1024]; + char depBuf [256]; +}; + +class CProject //: public CIniFile +{ + public: + CProject(); + ~CProject(); + + bool NoProject(void); + int CloseDecision(void); + bool New(char * fileName, WORD fileOffset); + bool Open(char * fileName, WORD fileOffset); + + bool RelativeToAbsolute(char * relativePath); + bool AddFiles(void); + + bool OptionsDlg(void); + bool NewModuleDlg(void); + bool NewModule(char * srcFile, bool createHeader); + + void ZipSrcs(void); + void Explore(HWND hwnd); + + void Build(void); + void RebuildAll(void); + void RunTarget(void); + void MakeClean(void); + void BuildMakefile(void); + + bool SwitchCurrentDir(void); + + CMakefile Makefile; + + /* May be private members */ + int numFiles; + bool loaded; + bool modified; + bool buildMakefile; + int SavePrjFile(int decision); + + char szFileName[MAX_PATH]; + WORD nFileOffset; + WORD nFileExtension; + char szDirBuffer[MAX_PATH]; + + char zipDir[MAX_PATH]; + char zipFlags[256]; + + char compilerName[64]; + + protected: + + private: + void Reset(); + +CIniFile PrjFile; + COptionsDlg _OptionsDlg; + CNewModuleDlg _NewModuleDlg; + + int prjVer; +}; + +#endif diff --git a/rosapps/devutils/vmingw/rsrc.h b/rosapps/devutils/vmingw/rsrc.h new file mode 100644 index 00000000000..2003f47d156 --- /dev/null +++ b/rosapps/devutils/vmingw/rsrc.h @@ -0,0 +1,168 @@ +/******************************************************************** +* Module: resource.h. This is part of Visual-MinGW. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#define APP_VERSION "0.43a" +#define FULL_APP_VERSION "0.43 alpha" + +// Static control ---------------------------- +#define IDC_STATIC -1 + +// Bitmaps ---------------------------------- +#define IDB_TOOLBAR 10 +#define IDB_TREEVIEW 11 + +#define IDAPPLY 20 + +// Preferences Dialog ----------------------- +#define IDD_PREFERENCES 100 +#define IDC_PREF_TABS 101 + +#define IDD_ENVIRON 110 +#define IDC_SET_CCBIN 111 +#define IDC_CCBIN 112 +#define IDC_BROWSE_CC 113 +#define IDC_SET_CMDBIN 114 +#define IDC_CMDBIN 115 +#define IDC_BROWSE_CMD 116 +#define IDC_AUTOEXEC 117 +#define IDC_ENV_VIEW 118 +/*#define IDC_CC_INCDIR 101 +#define IDC_BROWSE 102*/ + +// Find Dialog ------------------------------- +#define IDD_FIND 120 +#define IDC_FINDWHAT 121 +#define IDC_WHOLEWORD 122 +#define IDC_MATCHCASE 123 +#define IDC_REGEXP 124 +#define IDC_WRAP 125 +#define IDC_UNSLASH 126 +#define IDC_DIRECTIONUP 127 +#define IDC_DIRECTIONDOWN 128 + +// Replace ---------------------------------- +#define IDD_REPLACE 130 +#define IDC_REPLACEWITH 131 +#define IDC_REPLACE 132 +#define IDC_REPLACEALL 133 +#define IDC_REPLACEINSEL 134 + +// Find in files ------------------------------- +#define IDD_GREP 135 +#define IDC_GFILTER 136 +#define IDC_GDIR 137 +#define IDC_GBROWSE 139 + +// New module ------------------------------ +#define IDD_NEW_MODULE 140 +#define IDC_HEADER 141 + +// Options ---------------------------------- +#define IDD_OPTION 150 +#define IDC_OPTION_TABS 151 +#define IDC_HELP_BTN 152 + +// General tab --------------------------------- +#define IDD_GENERAL_PANE 160 +#define IDC_STATLIB 161 +#define IDC_DLL 162 +#define IDC_CONSOLE 163 +#define IDC_GUIEXE 164 +#define IDC_DBGSYM 165 +#define IDC_LANGC 166 +#define IDC_LANGCPP 167 +#define IDC_MKF_NAME 168 +#define IDC_MKF_DIR 169 +#define IDC_USER_MKF 170 +#define IDC_TGT_NAME 171 +#define IDC_TGT_DIR 172 + +// Compiler tab ----------------------------- +#define IDD_COMPILER 180 +#define IDC_CPPFLAGS 181 +#define IDC_WARNING 182 +#define IDC_OPTIMIZ 183 +#define IDC_CFLAGS 184 +#define IDC_INCDIRS 185 + +// Linker tab -------------------------------- +#define IDD_LINKER 190 +#define IDC_LDSTRIP 191 +#define IDC_LDOPTS 192 +#define IDC_LDLIBS 193 +#define IDC_LIBDIRS 194 + +#define IDD_ZIP 200 +#define IDC_INFOZIP 201 +#define IDC_TAR_GZIP 202 +#define IDC_TAR_BZ2 203 +#define IDC_ZIP_TEST 204 +#define IDC_ZIP_DIR 205 +#define IDC_ZIPFLAGS 206 +// About ------------------------------------ +#define IDD_ABOUT 210 + +#define IDD_COMMAND 220 +#define IDC_CMDLINE 221 +// Menu ------------------------------------- +#define ID_MENU 1000 +#define IDM_NEW 1001 +#define IDM_OPEN 1002 +//#define IDM_CLOSE 1003 +#define IDM_NEW_PROJECT 1004 +#define IDM_OPEN_PROJECT 1005 +#define IDM_SAVE_PROJECT 1006 +#define IDM_CLOSE_PROJECT 1007 +#define IDM_SAVE 1008 +#define IDM_SAVEAS 1009 +#define IDM_SAVEALL 1010 +#define IDM_PREFERENCES 1011 +#define IDM_PAGESETUP 1012 +#define IDM_PRINT 1013 +#define IDM_QUIT 1014 + +#define IDM_UNDO 1020 +#define IDM_REDO 1021 +#define IDM_CUT 1022 +#define IDM_COPY 1023 +#define IDM_PASTE 1024 +#define IDM_SELECTALL 1025 + +#define IDM_FIND 1030 +#define IDM_REPLACE 1031 +#define IDM_GREP 1032 + +#define IDM_CASCADE 1040 +#define IDM_TILEHORZ 1041 +#define IDM_TILEVERT 1042 +#define IDM_ARRANGE 1043 + +#define IDM_NEW_MODULE 1050 +#define IDM_ADD 1051 +#define IDM_REMOVE_FILE 1052 +#define IDM_REMOVE_MODULE 1053 +#define IDM_OPTION 1054 +#define IDM_ZIP_SRCS 1055 +#define IDM_EXPLORE 1056 + +#define IDM_BUILD 1060 +#define IDM_REBUILDALL 1061 +#define IDM_RUN_TARGET 1062 +#define IDM_MKCLEAN 1063 +#define IDM_MKF_BUILD 1064 +#define IDM_RUN_CMD 1065 + +#define IDM_TEST 1070 + +#define IDM_HELP 1080 +#define IDM_ABOUT 1081 + +#define ID_POPMENU 1100 + +#define ID_FIRSTCHILD 2000 + diff --git a/rosapps/devutils/vmingw/toolbar.bmp b/rosapps/devutils/vmingw/toolbar.bmp new file mode 100644 index 0000000000000000000000000000000000000000..17c5497cf7ca606773ca35eec4ca9cf301a87a78 GIT binary patch literal 4918 zcmcJSZERE58OQ$=OU{SVMQKd)u^mNP1erwHO^HFHxC1epCXOjD%U6%`;w=?29Ta~7 z$)h7O-PTxHI{8CC%oTBGby1a)pc#b^iG~Z#m>@-Yla|<6TAXVWOE@c9z5hA)Ui*dw zw4v?B=bm$)bIx;~-}yiHC62e6UxYlGEx`BKDzMbDtU-;m<2za<&ue6dZa4?#f$YeD7QkJ5wA2VXngH8D9z1i zW&cT*ntfdRIP3RnQ0s3194*+ocPrp;LX)ovPKSc}Mh`asU^i-O18A)EqG5|4ja$8_ zaX8W7ba0Lbjcjjoyor{ByV30Q;C0Udz}JBmZwJs3K-0dHsPX#IbToh;?b*#KPIR#B z+50y395{%#4<3ZK!vTlS2?ysKI&uikfCpZ$6Mmlu0lx=t{^SULeB>DWj>6;jVefH2 z_WMr3=?~zL|9$-Qop*4AcE8_?6FxtVpE`wKoH>I_`%deIt8!4giuQe zp+FENe;5cwfZu#U=mc7S6^8dh2=D(gh(I_5Unq<~FalpVg3~<_v|jp*wkU0Jc*Ak{ zBT=#?5QxSRh!4P74k3_bnc|N8 zrLsiJVthQ$x`b3Vi?0_JFkLEPe*PaQ+MM~FF7bHD;7qU@c>Nns$;y-nYn5ykoPz7NEFoHd7#0 z>of7XUGoXIi?}unilvcSVAh!Yk~bEsUZb<~!OhH&VpvEkerD(@pN!eU)RBjIj4|C> zX)NPr0CS9G=ZRy-Hgg31*zK-X#a3?~{!F~K$%WkHZkLsBrINtS<#GhB5~CZj?*59z zxZb(z<##jc*jxI_l2@K80ULl8EUo3AMcg(#%4S}J(;R=rffcivS?k;^jtvhV+W{*S zyIoNfm(5mZR`^+XTNAlldU9ePuI# zRy0bk$@x^<_myqyn%(RqZiP23V?npnm%K8kaXqhgZcpY_S7)alE3;Q-wD2uCVE~%- zEsG>KFR#tkeV98mH}UwZ5_qSOH#s&oR!UyWSd}`PQdM{buSEc_U;h-~L3?`Il^FS* z%Qn?xyT%vabcI(BsJ}>kyJLMUR0L|VSm^BB{<9eY;V3kR|t168JhH~-^w^CoZ36(Jd6dJD4 zsQQwN^20;&iig&$(D&w;sutA;YCfaz^H+=!#|nL|?G_7pwcb_F&$}llThi%NVpBSI zqZ#UgZD^Xjyn{8bh!r1#(o$e1wv?B^lDM)ggEo9u^_BUn>nl>(V$lcT;zeft*(&c@ zUeac`U=39Tc>zALFvnHL)Z$`ckvGvcm!i~FhOXqbwztciHaT0~tm{ckwhhgu+T6L6 zy#zIHn-shi-2VRJ!y*G>I`?%0KNs@KBX5#~{km6^z9N6M=d*lhEv?nYpsVZb#j`{< z;vg&yU0oFec^{BB4rGXXP>ckVSskr3F z*!tA;w0J=4tBX`7Fp;~vyZeCae>Zqlb9@zn4SmH;%>1Rk+zWXuEg3GQzUE-q|G2(+ z6(P*s!Ow8$fS5;_uPv!+?tZ4S6s;?HJ)ZXVrvle!+!M3nj?K04n*(mw)URjz(PFWg5j#9zx$TwEU$3RZ2r&5xX|le16QvgjS)>&f>5TSo54L zJfQV{rc|B28ZR^YX~1=ZBLpPyNSkmgq!6zpBYeJu_;sZdlUIzmL*zpB;Y^b-i`lHi zlZnLImC$!B_^-?(k=TaO7^{zwRi#fe3f{SlcnKdSv2L>#^LceqHGS-^;N9=BTA!}4 zd!2hy@J=>g)7KZkb$VNB!7ZT5#fOG4f><@85CcU(Mo^Ns8ok&*JR&gie3*h_e z+#C)cs?0;N_+XJMRSYZhdB5=Od78dftKHUe*=C*S$F^d literal 0 HcmV?d00001 diff --git a/rosapps/devutils/vmingw/treeview.bmp b/rosapps/devutils/vmingw/treeview.bmp new file mode 100644 index 0000000000000000000000000000000000000000..04b147f272f47287b944cae03eb9f4fcf135186b GIT binary patch literal 2870 zcmeH|KWx)L6vn?wNI`08D@dR~n-&m|(3U1NEu>NYIK?AsMz&_`MmD;Utz)t=x&va( z$m$J=#o1Vp=+-gWk!rs8&gZ01P%E(@^~Go3^E=<~zIV?~{nh3q)HbgG8TMLivuqQ% zs`rsF7d=mCAiB{8c%a=j7oORL@B8q-`51or$RMyb+eGzs4YeBE-VS#58)&s!@EL2@ zfL;Uen$mLcdF}53M_j~!ZMYBY9yGDrY2uC7Lf`>mXAxn*fuPf5%LRD55OPi*t^Gb4 zjS%vK=P}H<7vS9iTc-~MA(}zJb+*y%cG2#2(Ea40+v}n8K49yk(V3+|d51Nq&rR2eN-FjHG!5MHSi11&Ggpgd2@xsl#K`ZzfO5($YH1m{{{UjJuS zRworWGmVV$EYkAE^y$*|WY%xCHyU8qgA@Ktyx`1g&?wCF$%iW&o0AHZ@{D*UrIt6Q z52X@ZIZ>nPqZX=B#o}{l4y48UTqjR?Jc>@CC_JoeJSR_zrZUo}NwvIa`DQ-l#rvbF zGir3d6vYL^`dk4%xi9*h0(td1s1IPpV4NokEl*ZOGkQwwsXWyuJl-Gaqck~0vW!m_ z1-SfFfyETCP2MU{CGG|jYWI&@SUR&lnM<0MpXwE!HOZ%@S6651GXjzsih} z{I-7z&>@URJo5y7eqR*mE>mGzc=hdil?L3I(*k|z@DNRn*Xr7l}+|$0) qD2=1y(5a5iXF{hR<@daPJlW$1QCF7~-~P3evla!c8{sp5^?w2xK%njb literal 0 HcmV?d00001 diff --git a/rosapps/devutils/vmingw/vmingw.prj b/rosapps/devutils/vmingw/vmingw.prj new file mode 100644 index 00000000000..59188463956 --- /dev/null +++ b/rosapps/devutils/vmingw/vmingw.prj @@ -0,0 +1,91 @@ +[Project] +Signature = 40 +NumFiles = 15 +Compiler = mingw +BuildMakefile = 0 + +[Archives] +Directory = .\zip +Flags = *.prj .\bin\*.dll .\src\*.* .\include\*.h -x *.o + +[Makefile] +MAKE = make +CC = g++ +WRES = windres +TEST = gcc -v +Makefile = makefile +MakefileDir = .\src +Target = visual-mingw.exe +TargetDir = ..\bin +Build = 3 +Debug = 0 +Lang = 1 +CppFlags = -D_WIN32_IE=0x0400 +CcWarning = -W -Wall -pedantic +CcOptimize = -O2 +CcFlags = -fvtable-thunks -fno-rtti +IncDirs = -I ../include +LdStrip = -s +LdOptions = +LdLibraries = -lcomctl32 -lole32 +LdLibDirs = + +[File1] +Name = .\src\ChangeLog +Show = 0 + +[File2] +Name = .\src\CList.cpp +Show = 0 + +[File3] +Name = .\src\CList.h +Show = 0 + +[File4] +Name = .\src\editor.cpp +Show = 0 + +[File5] +Name = .\src\editor.h +Show = 0 + +[File6] +Name = .\src\main.cpp +Show = 0 + +[File7] +Name = .\src\main.h +Show = 0 + +[File8] +Name = .\src\process.cpp +Show = 0 + +[File9] +Name = .\src\process.h +Show = 0 + +[File10] +Name = .\src\project.cpp +Show = 0 + +[File11] +Name = .\src\project.h +Show = 0 + +[File12] +Name = .\src\rsrc.h +Show = 0 + +[File13] +Name = .\src\rsrc.rc +Show = 0 + +[File14] +Name = .\src\winui.cpp +Show = 0 + +[File15] +Name = .\src\winui.h +Show = 0 diff --git a/rosapps/devutils/vmingw/vmingw.rc b/rosapps/devutils/vmingw/vmingw.rc new file mode 100644 index 00000000000..0acb13d92fd --- /dev/null +++ b/rosapps/devutils/vmingw/vmingw.rc @@ -0,0 +1,399 @@ +/******************************************************************** +* Module: rsrc.rc. This is part of Visual-MinGW. +* +* Purpose: Resource file. +* +* Authors: Manu B. +* +* License: Visual-MinGW is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +* Revisions: 11/06/01. +* +********************************************************************/ +// For Borland Resource Workshop. (It doesn't like windows.h) +#ifndef WORKSHOP_INVOKED +#include "windows.h" +#endif +#include "rsrc.h" + +ID_MENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New" , IDM_NEW + MENUITEM "&Open" , IDM_OPEN + MENUITEM "&Close" , IDM_OPEN, GRAYED + MENUITEM SEPARATOR + MENUITEM "&New Project" , IDM_NEW_PROJECT + MENUITEM "&Open Project" , IDM_OPEN_PROJECT + MENUITEM "&Save Project" , IDM_SAVE_PROJECT + MENUITEM "&Close Project" , IDM_CLOSE_PROJECT + MENUITEM SEPARATOR + MENUITEM "&Save\tCtrl+S" , IDM_SAVE, GRAYED + MENUITEM "Save as" , IDM_SAVEAS, GRAYED + MENUITEM "&Save all" , IDM_SAVEALL + MENUITEM SEPARATOR + MENUITEM "Preferences" , IDM_PREFERENCES + MENUITEM "Page setup" , IDM_PAGESETUP, GRAYED + MENUITEM "&Print" , IDM_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Quit" , IDM_QUIT + END + + POPUP "&Edit", GRAYED + BEGIN + MENUITEM "&Undo" , IDM_UNDO + MENUITEM "&Redo" , IDM_REDO + MENUITEM SEPARATOR + MENUITEM "&Cut" , IDM_CUT + MENUITEM "&Copy" , IDM_COPY + MENUITEM "&Paste" , IDM_PASTE + MENUITEM SEPARATOR + MENUITEM "&Select all" , IDM_SELECTALL + END + + POPUP "&Find" + BEGIN + MENUITEM "&Search..." , IDM_FIND, GRAYED + MENUITEM "&Replace" , IDM_REPLACE, GRAYED + MENUITEM "Find in files" , IDM_GREP + END + + POPUP "&Window", GRAYED + BEGIN + MENUITEM "&Cascade" , IDM_CASCADE + MENUITEM "Tile &Horizontal" , IDM_TILEHORZ + MENUITEM "Tile &Vertical" , IDM_TILEVERT + MENUITEM "Arrange &Icons" , IDM_ARRANGE + END + + POPUP "&Project" + BEGIN + MENUITEM "&New Module" , IDM_NEW_MODULE + MENUITEM "&Add files" , IDM_ADD + MENUITEM "&Remove File" , IDM_REMOVE_FILE + MENUITEM "&Remove Module" , IDM_REMOVE_MODULE + MENUITEM "&Options" , IDM_OPTION + MENUITEM "&Create archive" , IDM_ZIP_SRCS + MENUITEM "&Explore" , IDM_EXPLORE + END + + POPUP "&Build" + BEGIN + MENUITEM "&Build" , IDM_BUILD + MENUITEM "&Rebuild All" , IDM_REBUILDALL + MENUITEM "&Run" , IDM_RUN_TARGET + MENUITEM "&Make Clean" , IDM_MKCLEAN + MENUITEM "&Build Makefile" , IDM_MKF_BUILD +#ifdef DEBUG + MENUITEM "&Run command" , IDM_RUN_CMD +#endif + END + +#ifdef DEBUG + POPUP "&Testing" + BEGIN + MENUITEM "a_new_procedure" , IDM_TEST + END +#endif + + POPUP "&?" + BEGIN + MENUITEM "&Help" , IDM_HELP, GRAYED + MENUITEM "&About" , IDM_ABOUT + END +END + +PopupMenu MENU +BEGIN + POPUP "&Editer" + BEGIN + MENUITEM "&Remove" , IDM_REMOVE_MODULE + END +END + +STRINGTABLE DISCARDABLE +BEGIN + IDM_NEW "New" + IDM_OPEN "Open" + IDM_SAVE "Save" + + IDM_CUT "Cut" + IDM_COPY "Copy" + IDM_PASTE "Paste" + + IDM_UNDO "Undo" + IDM_REDO "Redo" + IDM_FIND "Search" + + IDM_PRINT "Print" +END + +IDB_TOOLBAR BITMAP DISCARDABLE "toolbar.bmp" +IDB_TREEVIEW BITMAP DISCARDABLE "treeview.bmp" + +IDD_PREFERENCES DIALOG 0, 0, 283, 197 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Program Preferences" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Ok", IDOK, 115, 179, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 172, 179, 50, 14 + CONTROL "", IDC_PREF_TABS, "SysTabControl32", 0x0 | WS_CLIPSIBLINGS, 4, 4, 275, 169 + PUSHBUTTON "Apply", IDAPPLY, 229, 179, 50, 14, WS_DISABLED +END + +// "NOT WS_POPUP" is a workaround for windres prior version 2.11.92. +// LCC's weditres doesn't recognize this flag. +IDD_ENVIRON DIALOG 0, 0, 259, 148 +#ifdef __LCC__ +STYLE DS_CONTROL | WS_CHILD +#else +STYLE DS_CONTROL | WS_CHILD | NOT WS_POPUP +#endif +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Path variable", IDC_STATIC, 3, 3, 252, 140 + EDITTEXT IDC_CCBIN, 20, 26, 165, 12, ES_AUTOHSCROLL + AUTOCHECKBOX "Compiler bin directory", IDC_SET_CCBIN, 8, 16, 86, 10 + PUSHBUTTON "Browse", IDC_BROWSE_CC, 197, 25, 45, 14 + EDITTEXT IDC_CMDBIN, 20, 55, 165, 12, ES_AUTOHSCROLL + AUTOCHECKBOX "Default bin directory", IDC_SET_CMDBIN, 8, 45, 86, 10 + PUSHBUTTON "Browse", IDC_BROWSE_CMD, 197, 54, 45, 14 + AUTOCHECKBOX "Use default environment variables", IDC_AUTOEXEC, 8, 75, 125, 10 + EDITTEXT IDC_ENV_VIEW, 8, 88, 242, 49, ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, WS_EX_TRANSPARENT +END + +IDD_FIND DIALOG 0, 0, 236, 92 +STYLE DS_MODALFRAME | WS_VISIBLE | DS_CENTER | DS_3DLOOK | WS_POPUP | WS_CAPTION +CAPTION "Find" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Fi&nd what:",-1,4,8,42,8 + COMBOBOX IDC_FINDWHAT,47,7,128,50, WS_TABSTOP | CBS_DROPDOWN | CBS_AUTOHSCROLL + AUTOCHECKBOX "Match &whole word only", IDC_WHOLEWORD,4,26,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Match &case", IDC_MATCHCASE,4,38,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Regular &expression", IDC_REGEXP,4,50,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Wrap aroun&d", IDC_WRAP,4,62,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Transform &backslash expressions", IDC_UNSLASH,4,74,150,10, WS_GROUP | WS_TABSTOP + GROUPBOX "Direction",1072,107,26,68,28,WS_GROUP + AUTORADIOBUTTON "&Up",IDC_DIRECTIONUP,111,38,25,12, WS_GROUP + AUTORADIOBUTTON "&Down",IDC_DIRECTIONDOWN,138,38,35,12 + DEFPUSHBUTTON "&Find Next",IDOK,182,5,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,182,23,50,14 +END + +IDD_REPLACE DIALOG 0, 0, 260, 108 +STYLE DS_MODALFRAME | WS_VISIBLE | DS_CENTER | DS_3DLOOK | WS_POPUP | WS_CAPTION +CAPTION "Replace" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Fi&nd what:",-1,4,9,48,8 + COMBOBOX IDC_FINDWHAT,54,7,114,50,WS_TABSTOP | CBS_DROPDOWN | CBS_AUTOHSCROLL + LTEXT "Re&place with:",-1,4,26,48,8 + COMBOBOX IDC_REPLACEWITH,54,24,114,50,WS_TABSTOP | CBS_DROPDOWN | CBS_AUTOHSCROLL + AUTOCHECKBOX "Match &whole word only", IDC_WHOLEWORD,4,44,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Match &case", IDC_MATCHCASE,4,56,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Regular &expression", IDC_REGEXP,4,68,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Wrap aroun&d", IDC_WRAP,4,80,100,10, WS_GROUP | WS_TABSTOP + AUTOCHECKBOX "Transform &backslash expressions", IDC_UNSLASH,4,92,150,10, WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "&Find Next",IDOK,174,4,80,14,WS_GROUP + PUSHBUTTON "&Replace",IDC_REPLACE,174,21,80,14 + PUSHBUTTON "Replace &All",IDC_REPLACEALL,174,38,80,14 + PUSHBUTTON "Replace in &Selection",IDC_REPLACEINSEL,174,55,80,14 + PUSHBUTTON "Close",IDCANCEL,174,72,80,14 +END + +IDD_GREP DIALOG 26, 41, 226, 66 +STYLE DS_MODALFRAME | DS_CENTER | DS_3DLOOK | WS_POPUP | WS_CAPTION +CAPTION "Find in Files" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Fi&nd what:", IDC_STATIC, 5, 8, 35, 8, NOT WS_GROUP + COMBOBOX IDC_FINDWHAT, 40, 7, 120, 50, CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + LTEXT "F&iles:", IDC_STATIC, 5, 28, 30, 8, NOT WS_GROUP + COMBOBOX IDC_GFILTER, 40, 27, 120, 50, CBS_DROPDOWN | WS_BORDER | WS_TABSTOP + LTEXT "&Directory:", IDC_STATIC, 5, 48, 30, 8, NOT WS_GROUP + DEFPUSHBUTTON "&Find", IDOK, 168, 6, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 168, 26, 50, 14 + COMBOBOX 138, 40, 47, 120, 50, CBS_DROPDOWN | WS_BORDER | WS_TABSTOP + PUSHBUTTON "Browse", IDC_GBROWSE, 168, 46, 50, 14 +END + +IDD_OPTION DIALOGEX 0, 0, 252, 202 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Project options" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "", IDC_OPTION_TABS, "SysTabControl32", 0x8000, 4, 5, 244, 173 + PUSHBUTTON "Ok", IDOK, 79, 184, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 141, 184, 50, 14 + PUSHBUTTON "Help", IDC_HELP_BTN, 198, 184, 50, 14 +END + +IDD_GENERAL_PANE DIALOG 0, 0, 230, 139 +#ifdef __LCC__ +STYLE DS_CONTROL | WS_CHILD +#else +STYLE DS_CONTROL | WS_CHILD | NOT WS_POPUP +#endif +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Build what ?", IDC_STATIC, 5, 3, 107, 79 + AUTORADIOBUTTON "Static library", IDC_STATLIB, 12, 15, 59, 10, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "Dll", IDC_DLL, 12, 28, 59, 10 + AUTORADIOBUTTON "Console executable", IDC_CONSOLE, 12, 41, 78, 10 + AUTORADIOBUTTON "GUI executable", IDC_GUIEXE, 12, 54, 65, 10 + AUTOCHECKBOX "Generate debug symbols", IDC_DBGSYM, 12, 67, 97, 10 + GROUPBOX "Language", IDC_STATIC, 5, 86, 107, 46 + AUTORADIOBUTTON "C", IDC_LANGC, 12, 101, 25, 10, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "C++", IDC_LANGCPP, 12, 114, 29, 10 + GROUPBOX "Makefile", IDC_STATIC, 120, 3, 104, 67 + LTEXT "Name", IDC_STATIC, 124, 18, 23, 9 + EDITTEXT IDC_MKF_NAME, 156, 16, 61, 12, ES_AUTOHSCROLL + LTEXT "Directory", IDC_STATIC, 124, 35, 30, 9 + EDITTEXT IDC_MKF_DIR, 156, 33, 61, 12, ES_AUTOHSCROLL + AUTOCHECKBOX "User makefile", IDC_USER_MKF, 125, 52, 62, 10, WS_DISABLED + GROUPBOX "Output file", IDC_STATIC, 120, 76, 104, 56 + LTEXT "Name", IDC_STATIC, 124, 95, 23, 9 + EDITTEXT IDC_TGT_NAME, 156, 93, 61, 12, ES_AUTOHSCROLL + LTEXT "Directory", 133, 123, 112, 30, 9 + EDITTEXT IDC_TGT_DIR, 156, 110, 61, 12, ES_AUTOHSCROLL +END + +IDD_COMPILER DIALOG 0, 0, 230, 139 +#ifdef __LCC__ +STYLE DS_CONTROL | WS_CHILD +#else +STYLE DS_CONTROL | WS_CHILD | NOT WS_POPUP +#endif +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Compiler options", IDC_STATIC, 17, 11, 194, 111 + LTEXT "Preprocessor", IDC_STATIC, 22, 25, 46, 9 + EDITTEXT IDC_CPPFLAGS, 67, 24, 138, 12, ES_AUTOHSCROLL + LTEXT "Warning", IDC_STATIC, 22, 42, 31, 9 + EDITTEXT IDC_WARNING, 67, 40, 138, 12, ES_AUTOHSCROLL + LTEXT "Optimization", IDC_STATIC, 22, 58, 42, 9 + EDITTEXT IDC_OPTIMIZ, 67, 56, 138, 12, ES_AUTOHSCROLL + LTEXT "C/C++", IDC_STATIC, 23, 73, 24, 9 + EDITTEXT IDC_CFLAGS, 67, 72, 138, 12, ES_AUTOHSCROLL + LTEXT "Include directories", IDC_STATIC, 22, 92, 61, 9 + EDITTEXT IDC_INCDIRS, 22, 101, 183, 12, ES_AUTOHSCROLL +END + +IDD_LINKER DIALOG 0, 0, 230, 139 +#ifdef __LCC__ +STYLE DS_CONTROL | WS_CHILD +#else +STYLE DS_CONTROL | WS_CHILD | NOT WS_POPUP +#endif +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Linker", IDC_STATIC, 17, 16, 194, 103 + LTEXT "Strip", IDC_STATIC, 23, 37, 18, 9 + EDITTEXT IDC_LDSTRIP, 53, 36, 53, 12, ES_AUTOHSCROLL + LTEXT "Options", IDC_STATIC, 23, 53, 29, 9 + EDITTEXT IDC_LDOPTS, 53, 52, 151, 12, ES_AUTOHSCROLL + LTEXT "Libraries", IDC_STATIC, 23, 69, 34, 9 + EDITTEXT IDC_LDLIBS, 53, 68, 151, 12, ES_AUTOHSCROLL + LTEXT "Library directories", IDC_STATIC, 23, 88, 61, 9 + EDITTEXT IDC_LIBDIRS, 22, 98, 182, 12, ES_AUTOHSCROLL +END + +IDD_ZIP DIALOG 0, 0, 230, 139 +#ifdef __LCC__ +STYLE DS_CONTROL | WS_CHILD +#else +STYLE DS_CONTROL | WS_CHILD | NOT WS_POPUP +#endif +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Archiver", 304, 15, 7, 87, 58 + AUTORADIOBUTTON "Info-ZIP", IDC_INFOZIP, 20, 17, 39, 10, WS_GROUP + AUTORADIOBUTTON "Tar/Gzip", IDC_TAR_GZIP, 20, 32, 46, 10, WS_DISABLED + AUTORADIOBUTTON "Tar/Bz2", IDC_TAR_BZ2, 20, 47, 44, 10, WS_DISABLED + GROUPBOX "Output File", IDC_STATIC, 15, 71, 195, 56 + LTEXT "Directory", IDC_STATIC, 21, 86, 30, 9 + EDITTEXT IDC_ZIP_DIR, 56, 84, 61, 12, ES_AUTOHSCROLL + LTEXT "Options", IDC_STATIC, 21, 109, 29, 9 + EDITTEXT IDC_ZIPFLAGS, 51, 108, 151, 12, ES_AUTOHSCROLL + GROUPBOX "Date format", 207, 112, 7, 97, 58 + AUTORADIOBUTTON "mmddyyyy", 208, 117, 17, 53, 10 + AUTORADIOBUTTON "ddmmyyyy", 209, 117, 32, 49, 10, WS_DISABLED + AUTORADIOBUTTON "yyyymmdd", 211, 117, 47, 50, 10, WS_DISABLED +END + +IDD_NEW_MODULE DIALOG 226, 122, 142, 39 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "New module" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT 301, 6, 4, 84, 12, ES_AUTOHSCROLL + AUTOCHECKBOX "Create header", IDC_HEADER, 21, 22, 58, 10 + PUSHBUTTON "Ok", IDOK, 97, 3, 40, 14 + PUSHBUTTON "Cancel", IDCANCEL, 97, 22, 40, 14 +END + +IDD_ABOUT DIALOG 14, 26, 200, 78 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About this software..." +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "&OK", IDOK, 140, 18, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + ICON 500, IDC_STATIC, 16, 24, 18, 20, WS_GROUP + GROUPBOX "Informations", IDC_STATIC, 4, 3, 192, 70 + LTEXT "Version 0.42a", IDC_STATIC, 57, 15, 67, 52 +END + +IDD_COMMAND DIALOG 0, 0, 216, 45 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog Title" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Command line", IDC_STATIC, 5, 8, 48, 9 + EDITTEXT IDC_CMDLINE, 59, 7, 148, 12, ES_AUTOHSCROLL + PUSHBUTTON "Enter", IDOK, 157, 25, 50, 14 +END + +ACCELS ACCELERATORS +BEGIN + "S", IDM_SAVE, VIRTKEY, CONTROL +END + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,43,0,0 + PRODUCTVERSION 0,43,0,0 + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_PRERELEASE +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "04090000" + BEGIN + VALUE "CompanyName", "Visual-MinGW project\0" + VALUE "FileDescription", "Visual-MinGW\0" + VALUE "FileVersion", FULL_APP_VERSION + VALUE "InternalName", "visual-mingw\0" + VALUE "LegalCopyright", "Copyright (C) 2001 Manu B\0" + VALUE "OriginalFilename", "visual-mingw.exe\0" + VALUE "ProductName", "Visual-MinGW\0" + VALUE "ProductVersion", FULL_APP_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 0 + END +END + diff --git a/rosapps/devutils/vmingw/winui.cpp b/rosapps/devutils/vmingw/winui.cpp new file mode 100644 index 00000000000..9b36390ab2a --- /dev/null +++ b/rosapps/devutils/vmingw/winui.cpp @@ -0,0 +1,2117 @@ +/******************************************************************** +* Module: winui.cpp. This is part of WinUI. +* +* Purpose: WinUI main module. Contains procedures relative to User Interface +* and general purpose procedures. +* +* Authors: Manu B. +* +* License: WinUI is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +* Revisions: +* Manu B. 11/19/01 OpenDlg & SaveDlg enhancement. +* Manu B. 12/07/01 CIniFile created. +* Manu B. 12/15/01 CWinApp created. +* +********************************************************************/ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include "winui.h" + +// Callback procedures. +LRESULT CALLBACK MainWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); + +// Declare a CMessageBox instance to use anywhere in the whole app. +CMessageBox MsgBox; + + +/******************************************************************** +* Function: char *StpCpy(char *dest, const char *src). +* +* Purpose: stpcpy clone. +* +* Revisions: +* +********************************************************************/ +char *StpCpy(char *dest, const char *src){ + while (*src != '\0'){ + *dest = *src; + src++; + dest++; + } +return dest; +} + +size_t strcpylen(char *dest, const char *src){ + char * start = dest; + while (*src != '\0'){ + *dest = *src; + dest++; + src++; + } + *dest = '\0'; +return (dest-start); +} + + +/******************************************************************** +* Class: CChrono. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CChrono::CChrono(){ + _time = 0; +} + +CChrono::~CChrono(){ +} + +void CChrono::Start(void){ + _time = ::GetTickCount(); +} + +DWORD CChrono::Stop(void){ + DWORD diff = ::GetTickCount() - _time; + _time = 0; +return diff; +} + + +/******************************************************************** +* Class: Base Window class. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CWindow::CWindow(){ + _pParent = NULL; + _hInst = 0; + _hWnd = 0; + _lParam = NULL; +} + +CWindow::~CWindow(){ +} + +HWND CWindow::CreateEx( + CWindow * pWindow, + DWORD dwExStyle, + LPCTSTR lpClassName, + LPCTSTR lpWindowName, + DWORD dwStyle, + int x, int y, int nWidth, int nHeight, + HMENU hMenu, + LPVOID lpParam){ + + // Store a pointer to parent class and to lpParam. + _pParent = pWindow; + _lParam = lpParam; + + // Get parent class handles. + HWND hParent; + HINSTANCE hInst; + + if(_pParent){ + // Have a parent window. + hParent = _pParent->_hWnd; + hInst = _pParent->_hInst; + }else{ + // Parent window is desktop. + hParent = 0; + hInst = GetModuleHandle(NULL); + } + + _hWnd = CreateWindowEx( + dwExStyle, + lpClassName, + lpWindowName, + dwStyle, + x, + y, + nWidth, + nHeight, + hParent, + (HMENU) hMenu, + hInst, + this); // Retrieve lpParam using this->_lParam. + +return _hWnd; +} + +HWND CWindow::GetId(void){ +return _hWnd; +} + +LONG CWindow::SetLong(int nIndex, LONG dwNewLong){ +return ::SetWindowLong(_hWnd, nIndex, dwNewLong); +} + +LONG CWindow::GetLong(int nIndex){ +return ::GetWindowLong(_hWnd, nIndex); +} + +LRESULT CWindow::SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam){ +return ::SendMessage(_hWnd, Msg, wParam, lParam); +} + +bool CWindow::SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags){ +return ::SetWindowPos(_hWnd, hInsertAfter, x, y, width, height, uFlags); +} + +bool CWindow::Show(int nCmdShow){ +return ::ShowWindow(_hWnd, nCmdShow); +} + +bool CWindow::Hide(void){ +return ::ShowWindow(_hWnd, SW_HIDE); +} + +HWND CWindow::SetFocus(void){ +return ::SetFocus(_hWnd); +} + +/******************************************************************** +* Class: CWinBase. +* +* Purpose: Base Application class. +* +* Revisions: +* +********************************************************************/ +CWinBase::CWinBase(){ + hPrevInst = 0; + lpCmdLine = NULL; + nCmdShow = SW_SHOW; + + isWinNT = false; + strcpy( appName, "CWinBase"); +} + +CWinBase::~CWinBase(){ +} + +bool CWinBase::Init(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, + int nCmdShow){ + _hInst = hInstance; + hPrevInst = hPrevInstance; + lpCmdLine = lpCmdLine; + nCmdShow = nCmdShow; +return true; +} + +bool CWinBase::SetName(char * name, char * version){ + strcpy(appName, name); + strcat(appName, " "); + + if(version) + strcat(appName, version); +return true; +} + +bool CWinBase::IsWinNT(void){ + + OSVERSIONINFO osv = {sizeof(OSVERSIONINFO), 0, 0, 0, 0, ""}; + GetVersionEx(&osv); + + isWinNT = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT); +return isWinNT; +} + +void CWinBase::ParseCmdLine(char * outBuff){ + int len = 0; + outBuff[len] = '\0'; + + LPTSTR cmdLine = GetCommandLine(); + + while (*cmdLine){ + if (*cmdLine == '\"'){ + cmdLine++; + while (*cmdLine && *cmdLine != '\"'){ + outBuff[len] = *cmdLine; + len++; + cmdLine++; + } + break; + }else{ + while (*cmdLine && *cmdLine != ' '){ + outBuff[len] = *cmdLine; + len++; + cmdLine++; + } + break; + } + } + outBuff[len] = '\0'; + SplitFileName(outBuff, 0); +return; +} + + +/******************************************************************** +* Class: CSDIBase. +* +* Purpose: Base SDI class. +* +* Revisions: +* +********************************************************************/ +CSDIBase::CSDIBase(){ +mainClass[0] = 0; +hAccel = NULL; +} + +CSDIBase::~CSDIBase(){ +} + +int CSDIBase::Run(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, + int nCmdShow){ + Init(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + if (!CustomInit()){ + Release(); + return 1; + } + + MSG Msg; + if (CreateUI()){ + while(GetMessage(&Msg, NULL, 0, 0)){ + if (!TranslateAccelerator(_hWnd, hAccel, &Msg)){ + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } + }else{ + MsgBox.DisplayFatal("CreateUI() failed !"); + } + + Release(); +return Msg.wParam; +} + +bool CSDIBase::CustomInit(void){ +return true; +} + +bool CSDIBase::Release(void){ +return true; +} + +bool CSDIBase::CreateUI(void){ +return false; +} + +bool CSDIBase::MainRegisterEx(const char * className){ + strcpy(mainClass, className); + + // Default values. + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = MainWndProc; + wc.hInstance = _hInst; + wc.lpszClassName = mainClass; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(CSDIBase *); +return RegisterClassEx(&wc); +} + +LRESULT CALLBACK CSDIBase::CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam){ + + switch (Message){ + case WM_DESTROY: + PostQuitMessage (0); + return 0; + } + +return DefWindowProc(_hWnd, Message, wParam, lParam); +} + +/******************************************************************** +* Callback procedure. +********************************************************************/ +LRESULT CALLBACK MainWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){ + // Get a pointer to the CWindow class that owns this window. + CSDIBase * pSdiBase = (CSDIBase *) (GetWindowLong(hwnd, 0)); + + if (pSdiBase == 0){ // The pointer isn't set yet. + if (Message == WM_NCCREATE){ + // First, get the CSDIBase pointer. + pSdiBase = (CSDIBase *) ((CREATESTRUCT *)lParam)->lpCreateParams; + + // Attach pSdiBase and lParam to the window. + SetWindowLong(hwnd, 0, (LONG)(pSdiBase)); + SetWindowLong(hwnd, GWL_USERDATA, (LONG) pSdiBase->_lParam); + + // Store window handle. + pSdiBase->_hWnd = hwnd; + + // Let Windows continue the job. + return pSdiBase->CMainWndProc(Message, wParam, lParam); + }else{ + return DefWindowProc(hwnd, Message, wParam, lParam); + } + } +return pSdiBase->CMainWndProc(Message, wParam, lParam); +} + + +/******************************************************************** +* Class: CMDIBase. +* +* Purpose: Base MDI class. +* +* Revisions: +* +********************************************************************/ +CMDIBase::CMDIBase(){ +} + +CMDIBase::~CMDIBase(){ +} + +bool CMDIBase::ChildRegisterEx(const char * className){ + strcpy(MdiClient.childClass, className); + + // Default values. + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = ChildWndProc; + wc.hInstance = _hInst; + wc.lpszClassName = className; + wc.cbClsExtra = 0; + wc.cbWndExtra = 8;//sizeof(CMDIBase *); +return RegisterClassEx(&wc); +} + +int CMDIBase::Run(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, + int nCmdShow){ + Init(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + if (!CustomInit()){ + Release(); + return 1; + } + + MSG Msg; + if (CreateUI()){ + while(GetMessage(&Msg, NULL, 0, 0)){ + if (!TranslateAccelerator(_hWnd, hAccel, &Msg)){ + if (!TranslateMDISysAccel(MdiClient.GetId(), &Msg)){ + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } + } + }else{ + MsgBox.DisplayFatal("CreateUI() failed !"); + } + + Release(); +return Msg.wParam; +} + +bool CMDIBase::CustomInit(void){ +return true; +} + +bool CMDIBase::Release(void){ +return true; +} + +bool CMDIBase::CreateUI(void){ +return false; +} + +LRESULT CALLBACK CMDIBase::CMainWndProc(UINT, WPARAM, LPARAM){ +return 0; +} + +LRESULT CALLBACK CMDIBase::CChildWndProc(CWindow *, UINT, WPARAM, LPARAM){ +return 0; +} + +/******************************************************************** +* Child window callback procedure. +********************************************************************/ +LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){ + // Get a pointer to the CWindow class that owns this window. + CMDIChild * pMdiChild = (CMDIChild *) (GetWindowLong(hwnd, 0)); + + if (pMdiChild == 0){ // The pointer isn't set yet. + if (Message == WM_NCCREATE){ + // First, get the CMDIChild pointer. + pMdiChild = (CMDIChild *) ((MDICREATESTRUCT *) ((CREATESTRUCT *)lParam)->lpCreateParams)->lParam; + + // Attach pMdiChild and lParam to the window. + //MsgBox.DisplayLong((long) pMdiChild); + + SetWindowLong(hwnd, 0, (long)(pMdiChild)); + SetWindowLong(hwnd, GWL_USERDATA, (long) pMdiChild->_lParam); + + // Store window handle. + pMdiChild->_hWnd = hwnd; + + // Attach to a childList so that the list can destroy all MdiChild objects. + ((CMDIClient *) pMdiChild->_pParent)->childList.InsertFirst(pMdiChild); + + // Let Windows continue the job. + return pMdiChild->_pFrame->CChildWndProc(pMdiChild, Message, wParam, lParam); + }else{ + return DefWindowProc(hwnd, Message, wParam, lParam); + } + + // Free pMdiChild object. + }else if (Message == WM_NCDESTROY){ + ((CMDIClient *) pMdiChild->_pParent)->childList.Destroy(pMdiChild); + } +return pMdiChild->_pFrame->CChildWndProc(pMdiChild, Message, wParam, lParam); +} + + +/******************************************************************** +* Class: CMDIClient. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CMDIClient::CMDIClient(){ + initialized = false; + childClass[0] = 0; +} + +CMDIClient::~CMDIClient(){ +} + +void CMDIClient::Init(int menuIndex, UINT idFirstChild){ + nPos = menuIndex; + + // ID of first created child. + ccs.idFirstChild = idFirstChild; + initialized = true; +} + +HWND CMDIClient::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId){ + + if (!pWindow || !initialized) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + // Get our "Window menu" handle. + ccs.hWindowMenu = GetSubMenu(GetMenu(_pParent->_hWnd), nPos); + + _hWnd = CreateWindowEx( + dwExStyle, + "mdiclient", + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + (LPVOID) &ccs); + +return _hWnd; +} + +LPARAM CMDIClient::GetParam(LPARAM lParam){ + MDICREATESTRUCT *mcs = (MDICREATESTRUCT *) ((CREATESTRUCT *) lParam)->lpCreateParams; +return mcs->lParam; +} + + +/******************************************************************** +* Class: CMDIChild. +* +* Purpose: Base Windows Class. +* +* Revisions: +* +********************************************************************/ +CMDIChild::CMDIChild(){ + _pFrame = NULL; +} + +CMDIChild::~CMDIChild(){ +} + +HWND CMDIChild::CreateEx(CMDIClient * pMdiClient, DWORD dwExStyle, DWORD dwStyle, char * caption, UINT resId, LPVOID lParam){ + + if (!pMdiClient || !pMdiClient->initialized) + return 0; + + // Store pointers, lParam and _hInst. + _pParent = pMdiClient; + _pFrame = (CMDIBase *) pMdiClient->_pParent; // Owner of CChildWndProc. + _lParam = lParam; + _hInst = _pParent->_hInst; + + HWND hwnd = CreateWindowEx( + dwExStyle, + pMdiClient->childClass, + caption, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + this); + +return hwnd; +} + + +/******************************************************************** +* Class: CDlgBase. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CDlgBase::CDlgBase(){ +} + +CDlgBase::~CDlgBase(){ +} + +HWND CDlgBase::Create(CWindow * pWindow, WORD wResId, RECT * Pos, LPARAM lParam){ + HWND hwnd = 0; + if (pWindow){ + hwnd = CreateParam(pWindow, wResId, lParam); + if (Pos) + SetPosition(0, Pos->left, Pos->top, Pos->right, Pos->bottom, 0); + } +return hwnd; +} + +int CDlgBase::CreateModal(CWindow * pWindow, WORD wResId, LPARAM lParam){ + if (pWindow == NULL) + return 0; + + // Don't create a modal dialog if a modeless one already exists. + else if (_hWnd != 0) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + _lParam = (LPVOID) lParam; + + // Get parent class handles. + _hInst = _pParent->_hInst; + +return ::DialogBoxParam(_hInst, MAKEINTRESOURCE(wResId), _pParent->_hWnd, + (DLGPROC) DlgProc, (long) this); +} + +HWND CDlgBase::CreateParam(CWindow * pWindow, WORD wResId, LPARAM lParam){ + if (pWindow == NULL) + return 0; + // Don't create a dialog twice. + else if (_hWnd != 0) + return _hWnd; + + // Store a pointer to parent class. + _pParent = pWindow; + _lParam = (LPVOID) lParam; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + HWND hwnd = CreateDialogParam(_hInst, + MAKEINTRESOURCE(wResId), + _pParent->_hWnd, + (DLGPROC) DlgProc, + (long) this); +return hwnd; +} + +BOOL CDlgBase::EndDlg(int nResult){ + if (_hWnd){ + BOOL result = ::EndDialog(_hWnd, nResult); + _hWnd = 0; + return result; + } +return false; +} + +HWND CDlgBase::GetItem(int nIDDlgItem){ +return ::GetDlgItem(_hWnd, nIDDlgItem); +} + +BOOL CDlgBase::SetItemText(HWND hItem, LPCTSTR lpString){ +return ::SendMessage(hItem, WM_SETTEXT, 0, (long)lpString); +} + +UINT CDlgBase::GetItemText(HWND hItem, LPTSTR lpString, int nMaxCount){ +return ::SendMessage(hItem, WM_GETTEXT, nMaxCount, (long)lpString); +} + +LRESULT CALLBACK CDlgBase::CDlgProc(UINT Message, WPARAM, LPARAM){ + + switch(Message){ + case WM_INITDIALOG: + return TRUE; + + case WM_CLOSE: + EndDlg(0); + break; + } +return FALSE; +} + + +/******************************************************************** +* Class: CTabbedDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CTabbedDlg::CTabbedDlg(){ + _hWndTab = 0; + Pos.left = 0; + Pos.top = 0; + Pos.right = 100; + Pos.bottom = 100; +} + +CTabbedDlg::~CTabbedDlg(){ +} + +bool CTabbedDlg::SetChildPosition(HWND hChild){ + if (!_hWndTab) + return false; + // Get tab's display area. + RECT area; + ::GetWindowRect(_hWndTab, &area); + ::ScreenToClient(_hWnd, (POINT *) &area.left); + ::ScreenToClient(_hWnd, (POINT *) &area.right); + ::SendMessage(_hWndTab, TCM_ADJUSTRECT, FALSE, (LPARAM) &area); + ::CopyRect(&Pos, &area); + + // Get child dialog's rect. + RECT child; + ::GetWindowRect(hChild, &child); + ::ScreenToClient(_hWnd, (POINT *) &child.left); + ::ScreenToClient(_hWnd, (POINT *) &child.right); + + // Center child dialog. + int childWidth = child.right-child.left; + int childHeight = child.bottom-child.top; + int hMargin = ((area.right-area.left)-childWidth)/2; + int vMargin = ((area.bottom-area.top)-childHeight)/2; + Pos.left += hMargin; + Pos.top += vMargin; + Pos.right = childWidth; + Pos.bottom = childHeight; + +return ::SetWindowPos(hChild, 0, Pos.left, Pos.top, Pos.right, Pos.bottom, 0); +} + +void CTabbedDlg::OnNotify(int, LPNMHDR notify){ + // Dispatch tab control messages. + switch (notify->code){ + case TCN_SELCHANGING: + OnSelChanging(notify); + break; + + case TCN_SELCHANGE: + OnSelChange(notify); + break; + } +} + +void CTabbedDlg::OnSelChanging(LPNMHDR notify){ + // Hide child dialog that is deselected. + if (notify->hwndFrom == _hWndTab){ + CWindow * pPaneDlg = (CWindow *) GetParam(); + if (pPaneDlg){ + if (pPaneDlg->_hWnd) + pPaneDlg->Hide(); + } + } +} + +void CTabbedDlg::OnSelChange(LPNMHDR notify){ + // Show child dialog that is selected. + if (notify->hwndFrom == _hWndTab){ + CWindow * pPaneDlg = (CWindow *) GetParam(); + if (pPaneDlg){ + if (pPaneDlg->_hWnd) + pPaneDlg->Show(); + pPaneDlg->SetFocus(); + } + } +} + +LPARAM CTabbedDlg::GetParam(void){ + if (!_hWndTab) + return false; + int iItem = ::SendMessage(_hWndTab, TCM_GETCURSEL, 0, 0); + + tcitem.mask = TCIF_PARAM; + BOOL result = ::SendMessage(_hWndTab, TCM_GETITEM, iItem, (long) &tcitem); + if (result) + return tcitem.lParam; +return 0; +} + + +/******************************************************************** +* Callback procedure. +********************************************************************/ +LRESULT CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){ + // Get a pointer to the CWindow class that owns this window. + CDlgBase * pDlgBase = (CDlgBase *) (GetWindowLong(hwnd, DWL_USER)); + + if (pDlgBase == 0){ // The pointer isn't set yet. + if (Message == WM_INITDIALOG){ + // First, get the CDlgBase pointer. + pDlgBase = (CDlgBase *) lParam; + + // Attach pDlgBase and lParam to the window. + SetWindowLong(hwnd, DWL_USER, (LONG) pDlgBase); + SetWindowLong(hwnd, GWL_USERDATA, (LONG) pDlgBase->_lParam); + + // Store window handle. + pDlgBase->_hWnd = hwnd; + + // Let Windows continue the job. + return pDlgBase->CDlgProc(Message, wParam, (LONG) pDlgBase->_lParam); + }else{ + return FALSE; + } + } +return pDlgBase->CDlgProc(Message, wParam, lParam); +} + + +/******************************************************************** +* Class: CToolBar. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CToolBar::CToolBar(){ +} + +CToolBar::~CToolBar(){ +} + +HWND CToolBar::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId){ + + if (!pWindow) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + TOOLBARCLASSNAME, + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + NULL); + + if(_hWnd) + // For backward compatibility. + ::SendMessage(_hWnd, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); +return _hWnd; +} + +LRESULT CToolBar::AddBitmap(UINT resId, int nBmp, HINSTANCE hInstance){ + if (!_hWnd) + return -1; + + // Add the bitmap containing button images to the toolbar. + TBADDBITMAP tbab; + if (hInstance == HINST_COMMCTRL) + tbab.hInst = hInstance; + else + tbab.hInst = _hInst; + tbab.nID = resId; +return ::SendMessage(_hWnd, TB_ADDBITMAP, (WPARAM) nBmp, (WPARAM) &tbab); +} + +BOOL CToolBar::AddButtons(TBBUTTON * tbButtons, UINT numButtons){ + if (!_hWnd) + return FALSE; + + // Add the buttons to the toolbar. +return ::SendMessage(_hWnd, TB_ADDBUTTONS, (WPARAM) numButtons, (LPARAM) tbButtons); +} + + +/******************************************************************** +* Class: CStatusBar. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CStatusBar::CStatusBar(){ + numParts = 0; +} + +CStatusBar::~CStatusBar(){ +} + +HWND CStatusBar::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId){ + + if (!pWindow) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + STATUSCLASSNAME, + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + NULL); + +return _hWnd; +} + +void CStatusBar::SetParts(int nParts, int * aWidths){ + numParts = nParts; + ::SendMessage(_hWnd, SB_SETPARTS, nParts, (LPARAM) aWidths); +} + +void CStatusBar::WriteString(char * string, int part){ + if (part <= numParts) + ::SendMessage(_hWnd, SB_SETTEXT, part, (LPARAM) string); +} + +void CStatusBar::WriteLong(long number, int part){ + char longbuf[10]; + itoa (number, longbuf, 10); + WriteString(longbuf, part); +} + + +/******************************************************************** +* Class: CTabCtrl. +* +* Purpose: Tab control. +* +* Revisions: +* +********************************************************************/ +CTabCtrl::CTabCtrl(){ +} + +CTabCtrl::~CTabCtrl(){ +} + +HWND CTabCtrl::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId, LPVOID lpParam){ + + if (!pWindow) + return 0; + + // TODO also use lpParam for each control ? + // Store a pointer to parent class and to lpParam. + _pParent = pWindow; + _lParam = lpParam; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + WC_TABCONTROL, + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + lpParam); + +return _hWnd; +} + +int CTabCtrl::InsertItem(int iItem, UINT mask, DWORD dwState, DWORD dwStateMask, + LPTSTR pszText, int cchTextMax, int iImage, LPARAM lParam){ + + tcitem.mask = mask; + + #if (_WIN32_IE >= 0x0300) + tcitem.dwState = dwState; + tcitem.dwStateMask = dwStateMask; + #else + tcitem.lpReserved1 = 0; + tcitem.lpReserved2 = 0; + #endif + + tcitem.pszText = pszText; + tcitem.cchTextMax = cchTextMax; + tcitem.iImage = iImage; + tcitem.lParam = lParam; + +return ::SendMessage(_hWnd, TCM_INSERTITEM, iItem, (long) &tcitem); +} + +BOOL CTabCtrl::SetItem_Param(int iItem, LPARAM lParam){ + + tcitem.mask = TCIF_PARAM; + tcitem.lParam = lParam; + +return ::SendMessage(_hWnd, TCM_SETITEM, iItem, (long) &tcitem); +} + +int CTabCtrl::GetCurSel(void){ + +return ::SendMessage(_hWnd, TCM_GETCURSEL, 0, 0); +} + +LPARAM CTabCtrl::GetItem_Param(int iItem){ + + tcitem.mask = TCIF_PARAM; + BOOL result = ::SendMessage(_hWnd, TCM_GETITEM, iItem, (long) &tcitem); + if (result) + return tcitem.lParam; +return 0; +} + + +/******************************************************************** +* Class: CTreeView. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CTreeView::CTreeView(){ +} + +CTreeView::~CTreeView(){ +} + +HWND CTreeView::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId, LPVOID lpParam){ + + if (!pWindow) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + WC_TREEVIEW, + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + lpParam); + +return _hWnd; +} + +HTREEITEM CTreeView::CreateItem(HTREEITEM hParent, HTREEITEM hInsertAfter, int iImage, LPTSTR pszText, LPARAM lParam){ + + tvi.hParent = hParent; + tvi.hInsertAfter = hInsertAfter; + + tvi.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_IMAGE + | TVIF_SELECTEDIMAGE | TVIF_PARAM ; + tvi.item.stateMask = TVIS_EXPANDED; + tvi.item.state = TVIS_EXPANDED; + tvi.item.pszText = pszText; + tvi.item.iImage = iImage; + tvi.item.iSelectedImage = iImage; + tvi.item.lParam = (LPARAM) lParam; + +return (HTREEITEM) ::SendMessage(_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvi); +} + +LPARAM CTreeView::GetSelectedItemParam(void){ + _TvItem.hItem = TreeView_GetSelection(_hWnd); + _TvItem.mask = TVIF_PARAM; + _TvItem.lParam = 0; + TreeView_GetItem(_hWnd, (long) &_TvItem); +return _TvItem.lParam; +} + +/******************************************************************** +* Class: CListView. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CListView::CListView(){ + lastRow = 0; +} + +CListView::~CListView(){ +} + +HWND CListView::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId){ + + if (!pWindow) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + WC_LISTVIEW, + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + NULL); + +return _hWnd; +} + +void CListView::Clear(void){ + // Win9x ListView clear is too slow. + int numitems = ::SendMessage(_hWnd, LVM_GETITEMCOUNT, 0, 0); + for (int n = 0; n < numitems; n++){ + ::SendMessage(_hWnd, LVM_DELETEITEM, (WPARAM) 0, 0); + } + lastRow = 0; +} + + +/******************************************************************** +* Class: CScintilla. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CScintilla::CScintilla(){ +} + +CScintilla::~CScintilla(){ +} + +HWND CScintilla::CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle, UINT resId, LPVOID lpParam){ + + if (!pWindow) + return 0; + + // Store a pointer to parent class. + _pParent = pWindow; + + // Get parent class handles. + _hInst = _pParent->_hInst; + + _hWnd = CreateWindowEx( + dwExStyle, + "Scintilla", + NULL, + dwStyle, + 0, + 0, + 100, + 100, + _pParent->_hWnd, + (HMENU) resId, + _hInst, + lpParam); + +return _hWnd; +} + + +/******************************************************************** +* Class: CSplitter. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CSplitter::CSplitter(){ + Pane1 = NULL; + Pane2 = NULL; + size = 4; + p = 0; + isActive = false; + initialized = false; +} + +CSplitter::~CSplitter(){ +} + +void CSplitter::Init(CWindow * pane1, CWindow * pane2, bool vertical, + int barPos, int barMode){ + Pane1 = pane1; + Pane2 = pane2; + + if(Pane1 && Pane2) + initialized = true; + + isVertical = vertical; + + p = barPos; + mode = barMode; +} + +bool CSplitter::Show(int){ +return false; +} + +bool CSplitter::Hide(void){ +return false; +} + +bool CSplitter::SetPosition(HWND, int x, int y, int width, int height, UINT){ + pos.left = x; + pos.top = y; + pos.right = width; + pos.bottom = height; + + if(isVertical) + SetVertPosition(); + else + SetHorzPosition(); +return true; +} + +void CSplitter::SetVertPosition(void){ + psize = p+size; + + barPos.left = pos.left+p; + barPos.top = pos.top; + barPos.right = size; + barPos.bottom = pos.bottom; + + Pane1->SetPosition(0, + pos.left, + pos.top, + p, + pos.bottom, + 0); + + Pane2->SetPosition(0, + pos.left +psize, + pos.top, + pos.right -psize, + pos.bottom, + 0); +} + +void CSplitter::SetHorzPosition(void){ + psize = p+size; + + barPos.left = pos.left; + barPos.top = pos.top+pos.bottom-psize; + barPos.right = pos.right; + barPos.bottom = size; + + Pane1->SetPosition(0, + pos.left, + pos.top, + pos.right, + pos.bottom -psize, + 0); + + Pane2->SetPosition(0, + pos.left, + pos.top +pos.bottom-p, + pos.right, + p, + 0); +} + +bool CSplitter::HaveMouse(HWND hwnd, short, short){ + POINT ptCursor; + ::GetCursorPos(&ptCursor); + POINT ptClient = ptCursor; + ::ScreenToClient(hwnd, &ptClient); + + if ( ptClient.x >= barPos.left + && ptClient.x <= barPos.left+barPos.right + && ptClient.y >= barPos.top + && ptClient.y <= barPos.top+barPos.bottom){ + return true; + } +return false; +} + +bool CSplitter::OnSetCursor(HWND hwnd, LPARAM){ + if(HaveMouse(hwnd, 0, 0)){ + if (isVertical){ + ::SetCursor(::LoadCursor(NULL, IDC_SIZEWE)); + return true; + }else{ + ::SetCursor(::LoadCursor(NULL, IDC_SIZENS)); + return true; + } + } +return false; +} + +bool CSplitter::OnLButtonDown(HWND hwnd, short xPos, short yPos){ + if (HaveMouse(hwnd, 0, 0)){ + // Begin of mouse capture. + isActive = true; + ::SetCapture(hwnd); + + // Save initial mouse position. + initialPos.x = xPos; + initialPos.y = yPos; + + // Converts bar position for Xor bar. + POINT xorPos; + RECT rect; + xorPos.x = barPos.left; + xorPos.y = barPos.top; + + ClientToWindow(hwnd, &xorPos, &rect); + + // Draw the Xor bar. + HDC hdc; + hdc = GetWindowDC(hwnd); + DrawXorBar(hdc, xorPos.x, xorPos.y, barPos.right, barPos.bottom); + + // Save initial position for future erasing. + initialXorPos.x = xorPos.x; + initialXorPos.y = xorPos.y; + + ReleaseDC(hwnd, hdc); + } +return isActive; +} + +void CSplitter::OnLButtonUp(HWND hwnd, short xPos, short yPos){ + if (isActive) { + + // Erase the Xor bar ********************* + HDC hdc; + hdc = GetWindowDC(hwnd); + DrawXorBar(hdc, initialXorPos.x, initialXorPos.y, barPos.right, barPos.bottom); + ReleaseDC(hwnd, hdc); + + // Move Splitter to new position ******************* + newPos.x = xPos; + newPos.y = yPos; + + if(isVertical) + deltaPos = newPos.x - initialPos.x; + else + deltaPos = newPos.y - initialPos.y;/**/ + + if (deltaPos != 0) + Move(barPos.left + deltaPos, barPos.top + deltaPos); + + // End of capture. + ::ReleaseCapture(); + isActive = false; + } +} + +void CSplitter::OnMouseMove(HWND hwnd, short xPos, short yPos){ + if (isActive) { + newPos.x = xPos; + newPos.y = yPos; + + // Draw the Xor bar ********************* + POINT xorPos; + RECT rect; + + if(isVertical){ + deltaPos = newPos.x - initialPos.x; + xorPos.x = barPos.left + deltaPos; + xorPos.y = barPos.top; + + // Convert coordinates. + ClientToWindow(hwnd, &xorPos, &rect); + + // Convert rect. + OffsetRect(&rect, -rect.left, -rect.top); + + if(xorPos.x < 20) + xorPos.x = 20; + if(xorPos.x > rect.right-24) + xorPos.x = rect.right-24; + }else{ + deltaPos = newPos.y - initialPos.y; + xorPos.x = barPos.left; + xorPos.y = barPos.top + deltaPos; + + // Convert coordinates. + ClientToWindow(hwnd, &xorPos, &rect); + + // Convert rect. + OffsetRect(&rect, -rect.left, -rect.top); + + if(xorPos.y < 20) + xorPos.y = 20; + if(xorPos.y > rect.bottom-24) + xorPos.y = rect.bottom-24; + } + + HDC hdc; + hdc = GetWindowDC(hwnd); + DrawXorBar(hdc, initialXorPos.x, initialXorPos.y, barPos.right, barPos.bottom); + DrawXorBar(hdc, xorPos.x, xorPos.y, barPos.right, barPos.bottom); + initialXorPos.x = xorPos.x; + initialXorPos.y = xorPos.y; + ReleaseDC(hwnd, hdc); + } +} + +void CSplitter::Move(int mouseX, int mouseY){ + + if(isVertical){ + p = mouseX; + SetVertPosition(); + }else{ + p = pos.bottom - size - mouseY+pos.top; + SetHorzPosition(); + } +} + +void CSplitter::ClientToWindow(HWND hwnd, POINT * pt, RECT * rect){ + // Bar position. + ClientToScreen(hwnd, pt); + // Window rect. + GetWindowRect(hwnd, rect); + + // Convert the bar coordinates relative to the top-left of the window. + pt->x -= rect->left; + pt->y -= rect->top; +} + +void CSplitter::DrawXorBar(HDC hdc, int x1, int y1, int width, int height){ + static WORD _dotPatternBmp[8] = + { + 0x00aa, 0x0055, 0x00aa, 0x0055, + 0x00aa, 0x0055, 0x00aa, 0x0055 + }; + + HBITMAP hbm; + HBRUSH hbr, hbrushOld; + + hbm = CreateBitmap(8, 8, 1, 1, _dotPatternBmp); + hbr = CreatePatternBrush(hbm); + + SetBrushOrgEx(hdc, x1, y1, 0); + hbrushOld = (HBRUSH)SelectObject(hdc, hbr); + + PatBlt(hdc, x1, y1, width, height, PATINVERT); + + SelectObject(hdc, hbrushOld); + + DeleteObject(hbr); + DeleteObject(hbm); +} + + +/******************************************************************** +* Class: CBitmap. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CBitmap::CBitmap(){ + hBitmap = NULL; +} + +CBitmap::~CBitmap(){ + if (hBitmap) + DeleteObject(hBitmap); +} + +HBITMAP CBitmap::Load(CWindow * pWindow, LPCTSTR lpBitmapName){ + if (!hBitmap) // Don't create twice. + hBitmap = ::LoadBitmap(pWindow->_hInst, lpBitmapName); +return hBitmap; +} + +HBITMAP CBitmap::Load(CWindow * pWindow, WORD wResId){ + if (!hBitmap) //Don't create twice. + hBitmap = ::LoadBitmap(pWindow->_hInst, MAKEINTRESOURCE(wResId)); +return hBitmap; +} + +BOOL CBitmap::Destroy(void){ + BOOL result = false; + if (hBitmap) + result = DeleteObject(hBitmap); +return result; +} + + +/******************************************************************** +* Class: CImageList. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CImageList::CImageList(){ + hImgList = NULL; +} + +CImageList::~CImageList(){ + if (hImgList) + ImageList_Destroy(hImgList); +} + +HIMAGELIST CImageList::Create(int cx, int cy, UINT flags, int cInitial, int cGrow){ + if (!hImgList) // Don't create twice. + hImgList = ::ImageList_Create(cx, cy, flags, cInitial, cGrow); +return hImgList; +} + +int CImageList::AddMasked(CBitmap * pBitmap, COLORREF crMask){ +return ImageList_AddMasked(hImgList, pBitmap->hBitmap, crMask); +} + + +/******************************************************************** +* Class: CMessageBox. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CMessageBox::CMessageBox(){ + hParent = 0; + strcpy(caption, "CMessageBox"); +} + +CMessageBox::~CMessageBox(){ +} + +void CMessageBox::SetParent(HWND hwnd){ + hParent = hwnd; +} + +void CMessageBox::SetCaption(char * string){ + strcpy(caption, string); +} + +void CMessageBox::DisplayString(char * string, char * substring, UINT uType){ + if(!substring){ + MessageBox (hParent, string, caption, uType); + }else{ + sprintf(msgBuf, string, substring); + MessageBox (hParent, msgBuf, caption, uType); + } +} + +void CMessageBox::DisplayFatal(char * string, char * substring){ + DisplayString(string, substring, MB_OK | MB_ICONERROR); +} + +void CMessageBox::DisplayWarning(char * string, char * substring){ + DisplayString(string, substring, MB_OK | MB_ICONWARNING); +} + +void CMessageBox::DisplayLong(long number){ + char longbuf[10]; + itoa (number, longbuf, 10); + DisplayString(longbuf); +} + +void CMessageBox::DisplayRect(RECT * rect){ + if (!rect) + return; + sprintf(msgBuf, "left: %ld top: %ld right: %ld bottom: %ld", rect->left, rect->top, rect->right, rect->bottom); + MessageBox (hParent, msgBuf, caption, MB_OK); +} + +int CMessageBox::Ask(char * question, bool canCancel){ + + if (canCancel){ + // Cancel button. + return MessageBox(hParent, question, caption, MB_YESNOCANCEL | MB_ICONWARNING); + }else{ + // No cancel. + return MessageBox(hParent, question, caption, MB_YESNO | MB_ICONWARNING); + } +} + +int CMessageBox::AskToSave(bool canCancel){ + + char question[] = "Save changes ?"; + + if (canCancel){ + // Cancel button. + return Ask(question, true); + }else{ + // No cancel. + return Ask(question, false); + } +} + + +/******************************************************************** +* Class: CFileDlgBase. +* +* Purpose: Open/Save Dlg. +* +* Revisions: +* +********************************************************************/ +CFileDlgBase::CFileDlgBase(){ + ofn.lStructSize = sizeof(OPENFILENAME); // DWORD + Reset(); +} + +CFileDlgBase::~CFileDlgBase(){ +} + +void CFileDlgBase::Reset(void){ + // Set methods. + ofn.lpstrTitle = 0; // LPCTSTR + ofn.nFilterIndex = 0; // DWORD + ofn.lpstrFilter = 0; // LPCTSTR + ofn.lpstrDefExt = 0; // LPCTSTR + ofn.Flags = 0; // DWORD + + ofn.lpstrInitialDir = 0; // LPCTSTR + + // Get methods. + nNextFileOffset = 0; + ofn.nFileOffset = 0; // WORD + ofn.nFileExtension = 0; // WORD + + // Unused. + ofn.hInstance = 0; // HINSTANCE + ofn.lpstrCustomFilter = 0; // LPTSTR + ofn.nMaxCustFilter = 0; // DWORD + ofn.lpstrFileTitle = 0; // LPTSTR + ofn.nMaxFileTitle = 0; // DWORD + ofn.lCustData = 0; // DWORD + ofn.lpfnHook = 0; // LPOFNHOOKPROC + ofn.lpTemplateName = 0; // LPCTSTR +} + +void CFileDlgBase::SetData(char * filter, char * defExt, DWORD flags){ + SetFilter(filter); + SetDefExt(defExt); + SetFlags(flags); +} + +void CFileDlgBase::SetTitle(char * title){ + ofn.lpstrTitle = title; +} + +void CFileDlgBase::SetFilterIndex(DWORD filterIndex){ + ofn.nFilterIndex = filterIndex; +} + +void CFileDlgBase::SetFilter(char * filter){ + ofn.lpstrFilter = filter; +} + +void CFileDlgBase::SetDefExt(char * defExt){ + ofn.lpstrDefExt = defExt; +} + +void CFileDlgBase::SetFlags(DWORD flags){ + ofn.Flags = flags; +} + +void CFileDlgBase::SetInitialDir(char * lpstrInitialDir){ + ofn.lpstrInitialDir = lpstrInitialDir; +} + +WORD CFileDlgBase::GetFileOffset(void){ +return ofn.nFileOffset; +} + +WORD CFileDlgBase::GetFileExtension(void){ +return ofn.nFileExtension; +} + +WORD CFileDlgBase::GetNextFileOffset(void){ + // Analyses a "path\0file1\0file2\0file[...]\0\0" string returned by Open/SaveDlg. + char * srcFiles = ofn.lpstrFile; + if (srcFiles){ + if ((ofn.Flags & OFN_ALLOWMULTISELECT) == OFN_ALLOWMULTISELECT){ + // Initialize first call. + if (!nNextFileOffset) + nNextFileOffset = ofn.nFileOffset; + // Parse the string. + while (srcFiles[nNextFileOffset] != '\0') + nNextFileOffset++; + // Get next char. + nNextFileOffset++; + // End of string ? + if (srcFiles[nNextFileOffset] == '\0') + nNextFileOffset = 0; + return nNextFileOffset; + } + } +return 0; +} + +bool CFileDlgBase::OpenFileName(CWindow * pWindow, char * pszFileName, DWORD nMaxFile){ + if (!pWindow) + return false; + + ofn.hwndOwner = pWindow->_hWnd; // HWND + ofn.lpstrFile = pszFileName; // LPTSTR + ofn.nMaxFile = nMaxFile; // DWORD + +return ::GetOpenFileName(&ofn); +} + +bool CFileDlgBase::SaveFileName(CWindow * pWindow, char * pszFileName, DWORD nMaxFile){ + if (!pWindow) + return false; + pszFileName[0] = '\0'; + ofn.hwndOwner = pWindow->_hWnd; // HWND + ofn.lpstrFile = pszFileName; // LPTSTR + ofn.nMaxFile = nMaxFile; // DWORD + +return ::GetSaveFileName(&ofn); +} + + +/******************************************************************** +* Class: CPath. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CPath::CPath(){ +} + +CPath::~CPath(){ +} + +bool CPath::ChangeDirectory(char * dir){ + return SetCurrentDirectory(dir); +} + + +/******************************************************************** +* Paths. +********************************************************************/ +void SplitFileName(char * dirName, char * fileName){ + int n; + int len = strlen (dirName); + + for (n = len; n > 2; n--){ + if (dirName[n] == '\\' ){ + if (fileName) + strcpy (fileName, &dirName[n+1]); + dirName[n+1] = 0; + break; + } + } +} + +bool ChangeFileExt(char * fileName, char * ext){ + int len = strlen(fileName); + for (int n=len; n > 0; n--){ + if (fileName[n] == '.'){ + fileName[n+1] = 0; + strcat(fileName, ext); + return true; + } + } +return false; // No file extension. +} + + +/******************************************************************** +* Class: CIniFile. +* +* Purpose: "GetPrivateProfileString()" like procedure. +* +* Revisions: +* +********************************************************************/ +CIniFile::CIniFile(){ + buffer = NULL; + pcurrent = NULL; + psection = NULL; +} + +CIniFile::~CIniFile(){ + Close(); +} + +void CIniFile::Close(void){ + if (buffer) + free(buffer); + buffer = NULL; + pcurrent = NULL; + psection = NULL; +} + +bool CIniFile::Load(char * fullPath){ + if (buffer) + Close(); + + FILE * file; + + /* FIXME: ZeroMemory because open/close projects can cause + GetString to found data from previous projects. */ +// ZeroMemory(buffer, MAX_BLOC_SIZE); + + file = fopen(fullPath, "rb"); + if (file){ + buffer = (char *) malloc(MAX_BLOC_SIZE); + if (!buffer) + return false; + fread(buffer, 1, MAX_BLOC_SIZE, file); + if (0 != fread(buffer, 1, sizeof(buffer), file)){ + MsgBox.DisplayString("CIniFile ERROR: OVERFOW"); + fclose(file); + Close(); + return false; + } + fclose(file); + + // Initialize current pointer. + pcurrent = buffer; + return true; + } +return false; +} + +int CIniFile::GetInt(char * key, char * section){ + + char integer[32]; + + if (GetString(integer, key, section)){ + return atoi(integer); + } + +return 0; +} + +//****************************************************** +// Reminder : +// GetPrivateProfileString("Section", "Key", "default_string", data, size, iniFilePath); +//****************************************************** +bool CIniFile::GetString(char * data, char * key, char * section){ + /* Copies data and returns true if successfull */ + char *pstop; + if (section){ + /* Parse from pcurrent until the end of buffer */ + pstop = pcurrent; + for ( ; ; ){ + if (*pcurrent == '\0'){ + /* Parse again from beginning to pstop */ + pcurrent = buffer; + for ( ; ; ){ + if (FindSection(pcurrent, section)) + break; // Found ! + if (pcurrent >= pstop) + return false; // Not found ! + } + } + if (FindSection(pcurrent, section)) + break; // Found ! + } + } + + if (psection){ + /* Section Found */ + pstop = pcurrent; + //MsgBox.DisplayString(pcurrent); + for ( ; ; ){ + if (*pcurrent == '\0' || *pcurrent == '['){ + /* Parse again from beginning to pstop */ + pcurrent = psection; + for ( ; ; ){ + if (FindData(pcurrent, key, data)) + break; // Found ! + if (pcurrent >= pstop) + return false; // Not found ! + } + } + if (FindData(pcurrent, key, data)) + break; // Found ! + } + } + //MsgBox.DisplayString(pcurrent); +return true; +} + +bool CIniFile::FindSection(char * s, char * section){ + /* Search the section through one line of text */ + /* Returns true if successful, false otherwise */ + /* This procedure increments current pointer to the end of line */ + + if (!section) + return false; + + bool sectionFound = false; + psection = NULL; + + /* Skip spaces and comments */ + s = SkipUnwanted(s); + + /* End of buffer ? */ + if (*s == '\0'){ + pcurrent = s; + return false; + + /* A section ? */ + }else if (*s == '['){ + s++; + if (*s == '\0'){ + pcurrent = s; + return false; + } + + /* Parse the section name */ + int len = strlen(section); + if (!strncmp(s, section, len)){ + s+=len; + if (*s == ']'){ + /* Section found ! */ + sectionFound = true; + } + } + } + + /* Increment current pointer until the end of current line */ + while (*s != '\0' && *s != '\n') + s++; + pcurrent = s; + + if (sectionFound) + psection = pcurrent; +return sectionFound; +} + +bool CIniFile::FindData(char * s, char * key, char * data){ + /* Search the key through one line of text */ + /* Returns true if successful, false otherwise */ + /* This procedure increments current pointer to the end of line */ + + bool keyFound = false; + /* Skip spaces and comments */ + s = SkipUnwanted(s); + + /* End of buffer ? End of section ? */ + if (*s == '\0' || *s == '['){ + pcurrent = s; + return false; + + /* Search the key */ + }else{ + int len = strlen(key); + /* Compare key and s */ + if (!strncmp(s, key, len)){ + s+=len; + /* Search an '=' sign */ + while (isspace(*s)){ + if (*s == '\n') + break; + s++; + } + + if (*s == '='){ + /* Key found ! */ + keyFound = true; + s++; + while (isspace(*s)){ + if (*s == '\n') + break; + s++; + } + + /* Copy data ! */ + s += CopyData(data, s); + } + } + } + + /* Increment current pointer until the end of current line */ + while (*s != '\0' && *s != '\n') + s++; + pcurrent = s; +return keyFound; +} + +long CIniFile::CopyData(char * data, char * s){ +/* Returns the number of characters copied not including the terminating null char */ + char *pdata = data; + while (*s != '\0' && *s != '\r' && *s != '\n'){ + *pdata = *s; + pdata++; + s++; + + /* @@ Overflow @@ + n++; + if (n == n_max){ + *data = '\0'; + return + }*/ + } + *pdata = '\0'; +return (pdata-data); +} + +char * CIniFile::SkipUnwanted(char *s){ + for ( ; ; ){ + /* End of buffer ? */ + if (*s == '\0') + return s; + if (isspace(*s)){ + /* Skip spaces */ + s++; + }else if (*s == ';'){ + /* Skip comments */ + char * end_of_line = strchr(s, '\n'); + if (end_of_line){ + /* End of comment */ + s = end_of_line+1; + continue; + }else{ + /* End of buffer */ + return end_of_line; + } + /* Done */ + }else{ + return s; + } + } +} + + +/******************************************************************** +* Class: CShellDlg. +* +* Purpose: +* +* Revisions: +* +********************************************************************/ +CShellDlg::CShellDlg(){ + // Get shell task allocator. + if(SHGetMalloc(&pMalloc) == (HRESULT) E_FAIL) + pMalloc = NULL; +} + +CShellDlg::~CShellDlg(){ + // Decrements the reference count. + if (pMalloc) + pMalloc->Release(); +} + +bool CShellDlg::BrowseForFolder(CWindow * pWindow, LPSTR pszDisplayName, + LPCSTR lpszTitle, UINT ulFlags, BFFCALLBACK lpfn, LPARAM lParam, int iImage){ + + // Initialize output buffer. + *pszDisplayName = '\0'; + // BROWSEINFO. + if (!pWindow) + bi.hwndOwner = 0; + else + bi.hwndOwner = pWindow->_hWnd; + bi.pidlRoot = NULL; + bi.pszDisplayName = pszDisplayName; + bi.lpszTitle = lpszTitle; + bi.ulFlags = ulFlags; + bi.lpfn = lpfn; + bi.lParam = lParam; + bi.iImage = iImage; + + LPITEMIDLIST pidl = SHBrowseForFolder(&bi); + if(!pidl) + return false; + + if(!SHGetPathFromIDList(pidl, pszDisplayName)) + return false; + + pMalloc->Free(pidl); +return true; +} + +CCriticalSection::CCriticalSection(){ + ::InitializeCriticalSection(&cs); +} + +CCriticalSection::~CCriticalSection(){ + ::DeleteCriticalSection(&cs); +} + +void CCriticalSection::Enter(){ + ::EnterCriticalSection(&cs); +} + +void CCriticalSection::Leave(){ + ::LeaveCriticalSection(&cs); +} + diff --git a/rosapps/devutils/vmingw/winui.h b/rosapps/devutils/vmingw/winui.h new file mode 100644 index 00000000000..b20ddb8ec58 --- /dev/null +++ b/rosapps/devutils/vmingw/winui.h @@ -0,0 +1,529 @@ +/******************************************************************** +* Module: winui.h. This is part of WinUI. +* +* License: WinUI is covered by GNU General Public License, +* Copyright (C) 2001 Manu B. +* See license.htm for more details. +* +********************************************************************/ +#ifndef WINUI_H +#define WINUI_H + +/* These are patched headers */ +#include "commdlg.h" +#include "commctrl.h" +#include +#include +#include +// OLE. +#include + +#include "CList.h" + +#define SPLSTYLE_HORZ 0 +#define SPLSTYLE_VERT 1 +#define SPLMODE_1 0 +#define SPLMODE_2 1 + +char *StpCpy(char *dest, const char *src); +size_t strcpylen(char *dest, const char *src); + +void SplitFileName(char * dirName, char * fileName); +bool ChangeFileExt(char * fileName, char * ext); + +class CMessageBox +{ + public: + CMessageBox(); + ~CMessageBox(); + + void SetParent(HWND hwnd); + void SetCaption(char * string); + void DisplayString(char * string, char * substring = NULL, UINT uType = MB_OK); + void DisplayWarning(char * string, char * substring = NULL); + void DisplayFatal(char * string, char * substring = NULL); + void DisplayLong(long number); + void DisplayRect(RECT * rect); + int Ask(char * question, bool canCancel); + int AskToSave(bool canCancel); + + protected: + HWND hParent; + char msgBuf[256]; + char caption[64]; + + private: +}; + +class CPath +{ + public: + CPath(); + ~CPath(); + + bool ChangeDirectory(char * dir); + + protected: + + private: + char pathBuf[MAX_PATH]; +}; + +class CWindow +{ + public: + CWindow(); + virtual ~CWindow(); + + virtual HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, + LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, + int nWidth, int nHeight, HMENU hMenu, LPVOID lpParam); + + HWND GetId(void); + LONG SetLong(int nIndex, LONG dwNewLong); + LONG GetLong(int nIndex); + LRESULT SendMessage(UINT msg, WPARAM wParam = 0, LPARAM lParam = 0); + + virtual bool SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags); + virtual bool Show(int nCmdShow = SW_SHOWNORMAL); + virtual bool Hide(void); + HWND SetFocus(void); + CWindow * _pParent; + HWND _hWnd; + HINSTANCE _hInst; + LPVOID _lParam; + + protected: + + private: +}; + +class CWinBase : public CWindow +{ + public: + CWinBase(); + ~CWinBase(); + + HINSTANCE hPrevInst; + LPSTR lpCmdLine; + int nCmdShow; + + char appName[64]; + char msgBuf[256]; + bool isWinNT; + + bool Init(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, + int nCmdShow); + bool SetName(char * name, char * version = NULL); + void ParseCmdLine(char * outBuff); + bool IsWinNT(void); + + bool ChangeDirectory(char * dir); + + protected: + + private: +}; + +class CSDIBase : public CWinBase +{ + public: + CSDIBase(); + virtual ~CSDIBase(); + + virtual int Run(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); + virtual bool CustomInit(void); + virtual bool Release(void); + virtual bool CreateUI(void); + bool MainRegisterEx(const char * className); + virtual LRESULT CALLBACK CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam); + + protected: + WNDCLASSEX wc; + HACCEL hAccel; + char mainClass[16]; + + private: +}; + +class CMDIChild; + +class CMDIClient : public CWindow +{ + public: + CMDIClient(); + ~CMDIClient(); + + void Init(int menuIndex, UINT idFirstChild); + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0); + LPARAM GetParam(LPARAM lParam); + + bool initialized; + char childClass[16]; + CList childList; + + protected: + CLIENTCREATESTRUCT ccs; + int nPos; + + private: +}; + +class UseOle +{ + public: + UseOle(){oleError = OleInitialize(NULL);} + ~UseOle(){OleUninitialize();} + HRESULT GetError(void){return oleError;} + protected: + HRESULT oleError; + private: +}; + +class CMDIBase : public CSDIBase +{ + public: + CMDIBase(); + virtual ~CMDIBase(); + + virtual int Run(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); + virtual bool CustomInit(void); + virtual bool Release(void); + virtual bool CreateUI(void); + bool ChildRegisterEx(const char * className); + virtual LRESULT CALLBACK CMainWndProc(UINT Message, WPARAM wParam, LPARAM lParam); + virtual LRESULT CALLBACK CChildWndProc(CWindow * pWnd, UINT Message, WPARAM wParam, LPARAM lParam); + + CMDIClient MdiClient; + + protected: + UseOle useOle; + + private: +}; + +class CMDIChild : public CNode, public CWindow +{ + public: + CMDIChild(); + virtual ~CMDIChild(); + + HWND CreateEx(CMDIClient * pMdiClient, DWORD dwExStyle, DWORD dwStyle, char * caption, UINT resId = 0, LPVOID lParam = NULL); + + CMDIBase * _pFrame; + + protected: + + private: +}; + +class CFileDlgBase : public CWindow +{ + public: + CFileDlgBase(); + ~CFileDlgBase(); + + void Reset(void); + void SetData(char * filter, char * defExt, DWORD flags); + void SetTitle(char * title); + void SetFilterIndex(DWORD filterIndex); + void SetFilter(char * filter); + void SetDefExt(char * defExt); + void SetFlags(DWORD flags); + void SetInitialDir(char * lpstrInitialDir); + + WORD GetFileOffset(void); + WORD GetFileExtension(void); + WORD GetNextFileOffset(void); + + bool OpenFileName(CWindow * pWindow, char * pszFileName, DWORD nMaxFile); + bool SaveFileName(CWindow * pWindow, char * pszFileName, DWORD nMaxFile); + OPENFILENAME ofn; + + protected: + + WORD nNextFileOffset; + private: +}; + +class CDlgBase : public CWindow +{ + public: + CDlgBase(); + virtual ~CDlgBase(); + + HWND Create(CWindow * pWindow, WORD wResId, RECT * Pos, LPARAM lParam); + int CreateModal(CWindow * pWindow, WORD wResId, LPARAM lParam); + HWND CreateParam(CWindow * pWindow, WORD wResId, LPARAM lParam); + BOOL EndDlg(int nResult); + virtual LRESULT CALLBACK CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam); + HWND GetItem(int nIDDlgItem); + BOOL SetItemText(HWND hItem, LPCTSTR lpString); + UINT GetItemText(HWND hItem, LPTSTR lpString, int nMaxCount); +/* BOOL SetItemInt(HWND hItem, UINT uValue, BOOL bSigned); + UINT GetItemInt(HWND hItem, BOOL *lpTranslated, BOOL bSigned); +*/ + protected: + + private: +}; + +class CTabbedDlg : public CDlgBase +{ + public: + CTabbedDlg(); + virtual ~CTabbedDlg(); + + virtual void OnNotify(int idCtrl, LPNMHDR notify); + virtual void OnSelChanging(LPNMHDR notify); + virtual void OnSelChange(LPNMHDR notify); + virtual bool SetChildPosition(HWND hChild); + + protected: + LPARAM GetParam(void); + HWND _hWndTab; + RECT Pos; + TCITEM tcitem; + + private: +}; + +class CToolBar : public CWindow +{ + public: + CToolBar(); + ~CToolBar(); + + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0); + LRESULT AddBitmap(UINT resId, int nBmp, HINSTANCE hInstance = 0); + BOOL AddButtons(TBBUTTON * tbButtons, UINT numButtons); + + protected: + + private: +}; + +class CBitmap +{ + public: + CBitmap(); + ~CBitmap(); + + HBITMAP Load(CWindow * pWindow, LPCTSTR lpBitmapName); + HBITMAP Load(CWindow * pWindow, WORD wResId); + BOOL Destroy(void); + + HBITMAP hBitmap; + + protected: + + private: +}; + +class CImageList +{ + public: + CImageList(); + ~CImageList(); + + HIMAGELIST Create(int cx, int cy, UINT flags, int cInitial, int cGrow); + int AddMasked(CBitmap * pBitmap, COLORREF crMask); + HIMAGELIST GetId(void){return hImgList;}; + + protected: + HIMAGELIST hImgList; + + private: +}; + +class CTabCtrl : public CWindow +{ + public: + CTabCtrl(); + ~CTabCtrl(); + + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0, LPVOID lParam = NULL); + BOOL SetItem_Param(int iItem, LPARAM lParam); + LPARAM GetItem_Param(int iItem); + int GetCurSel(void); + int InsertItem(int iItem, UINT mask, DWORD dwState, DWORD dwStateMask, + LPTSTR pszText, int cchTextMax, int iImage, LPARAM lParam); + + protected: + TCITEM tcitem; + + private: +}; + +class CTreeView : public CWindow +{ + public: + CTreeView(); + ~CTreeView(); + + TVINSERTSTRUCT tvi; + TVITEM _TvItem; + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0, LPVOID lParam = NULL); + HTREEITEM CreateItem(HTREEITEM hParent, HTREEITEM hInsertAfter, int iImage, LPTSTR pszText, LPARAM lParam); + LPARAM GetSelectedItemParam(void); + + protected: + private: +}; + +class CScintilla : public CWindow +{ + public: + CScintilla(); + ~CScintilla(); + + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0, LPVOID lParam = NULL); + + protected: + private: +}; + +class CListView : public CWindow +{ + public: + CListView(); + ~CListView(); + + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0); + void Clear(void); + + protected: + DWORD lastRow; + + private: +}; + +class CStatusBar : public CWindow +{ + public: + CStatusBar(); + ~CStatusBar(); + + HWND CreateEx(CWindow * pWindow, DWORD dwExStyle, DWORD dwStyle = WS_CHILD, UINT resId = 0); + void SetParts(int nParts, int * aWidths); + + void WriteString(char * string, int part); + void WriteLong(long number, int part); + + protected: + + private: + int numParts; +}; + +class CSplitter : public CWindow +{ + public: + CSplitter(); + ~CSplitter(); + + void Init(CWindow * pane1, CWindow * pane2, bool vertical, + int barPos, int barMode); + bool SetPosition(HWND hInsertAfter, int x, int y, int width, int height, UINT uFlags); + bool Show(int nCmdShow = SW_SHOWNORMAL); + bool Hide(void); + bool HaveMouse(HWND hwnd, short xPos, short yPos); + void Move(int mouseX, int mouseY); + bool OnLButtonDown(HWND hwnd, short xPos, short yPos); + void OnMouseMove(HWND hwnd, short xPos, short yPos); + void OnLButtonUp(HWND hwnd, short xPos, short yPos); + bool OnSetCursor(HWND hwnd, LPARAM lParam); + + protected: + void SetVertPosition(void); + void SetHorzPosition(void); + void DrawXorBar(HDC hdc, int x1, int y1, int width, int height); + void ClientToWindow(HWND hwnd, POINT * pt, RECT * rect); + + CWindow * Pane1; + CWindow * Pane2; + int p; + int size; + int psize; + bool isVertical; + int mode; + bool isActive; + RECT pos; + RECT barPos; + int deltaPos; + POINT initialXorPos; + + POINT initialPos; + POINT newPos; + private: + bool initialized; +}; + +#define MAX_BLOC_SIZE 16384 +class CIniFile +{ + public: + CIniFile(); + ~CIniFile(); + + bool Load(char * fullPath); + void Close(void); + bool GetString(char * data, char * key, char * section = NULL); + int GetInt(char * key, char * section = NULL); + + protected: + + private: + + char * buffer; + char * pcurrent; + char * psection; + + bool FindSection(char * pcurrent, char * section); + bool FindData(char * s, char * key, char * data); + long CopyData(char * data, char * s); + char *SkipUnwanted(char *s); +}; + +class CChrono +{ + public: + CChrono(); + ~CChrono(); + + void Start(void); + DWORD Stop(void); + + protected: + DWORD _time; + + private: +}; + +class CShellDlg +{ + public: + CShellDlg(); + ~CShellDlg(); + bool BrowseForFolder(CWindow * pWindow, LPSTR pszDisplayName, LPCSTR lpszTitle, + UINT ulFlags, BFFCALLBACK lpfn=0, LPARAM lParam=0, int iImage=0); + + protected: + IMalloc* pMalloc; + BROWSEINFO bi; + + private: +}; + +class CCriticalSection +{ +public: + CCriticalSection(); + ~CCriticalSection(); + void Enter(); + void Leave(); +private: + CRITICAL_SECTION cs; +}; + +#endif