diff options
author | Akshay Chipkar | 2016-04-22 18:12:44 +0530 |
---|---|---|
committer | Akshay Chipkar | 2016-04-22 18:12:44 +0530 |
commit | 88dfbfa8a9ea63b72c5d185e1678c98b7585e8b3 (patch) | |
tree | 646a6cbb5e381cafd656a1dc0b4418f4102060a9 /ldmicro/maincontrols.cpp | |
download | OpenPLC-ldmicro-88dfbfa8a9ea63b72c5d185e1678c98b7585e8b3.tar.gz OpenPLC-ldmicro-88dfbfa8a9ea63b72c5d185e1678c98b7585e8b3.tar.bz2 OpenPLC-ldmicro-88dfbfa8a9ea63b72c5d185e1678c98b7585e8b3.zip |
added all relevant files for ldmicro
Diffstat (limited to 'ldmicro/maincontrols.cpp')
-rw-r--r-- | ldmicro/maincontrols.cpp | 745 |
1 files changed, 745 insertions, 0 deletions
diff --git a/ldmicro/maincontrols.cpp b/ldmicro/maincontrols.cpp new file mode 100644 index 0000000..25c05f6 --- /dev/null +++ b/ldmicro/maincontrols.cpp @@ -0,0 +1,745 @@ +//-----------------------------------------------------------------------------
+// Copyright 2007 Jonathan Westhues
+//
+// This file is part of LDmicro.
+//
+// LDmicro 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 3 of the License, or
+// (at your option) any later version.
+//
+// LDmicro 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 LDmicro. If not, see <http://www.gnu.org/licenses/>.
+//------
+//
+// Common controls in the main window. The main window consists of the drawing
+// area, where the ladder diagram is displayed, plus various controls for
+// scrolling, I/O list, menus.
+// Jonathan Westhues, Nov 2004
+//-----------------------------------------------------------------------------
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "ldmicro.h"
+
+// scrollbars for the ladder logic area
+static HWND HorizScrollBar;
+static HWND VertScrollBar;
+int ScrollWidth;
+int ScrollHeight;
+BOOL NeedHoriz;
+
+// status bar at the bottom of the screen, to display settings
+static HWND StatusBar;
+
+// have to get back to the menus to gray/ungray, check/uncheck things
+static HMENU FileMenu;
+static HMENU EditMenu;
+static HMENU InstructionMenu;
+static HMENU ProcessorMenu;
+static HMENU SimulateMenu;
+static HMENU TopMenu;
+
+// listview used to maintain the list of I/O pins with symbolic names, plus
+// the internal relay too
+HWND IoList;
+static int IoListSelectionPoint;
+static BOOL IoListOutOfSync;
+int IoListHeight;
+int IoListTop;
+
+// whether the simulation is running in real time
+static BOOL RealTimeSimulationRunning;
+
+//-----------------------------------------------------------------------------
+// Create the standard Windows controls used in the main window: a Listview
+// for the I/O list, and a status bar for settings.
+//-----------------------------------------------------------------------------
+void MakeMainWindowControls(void)
+{
+ LVCOLUMN lvc;
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+#define LV_ADD_COLUMN(hWnd, i, w, s) do { \
+ lvc.iSubItem = i; \
+ lvc.pszText = s; \
+ lvc.iOrder = 0; \
+ lvc.cx = w; \
+ ListView_InsertColumn(hWnd, i, &lvc); \
+ } while(0)
+ IoList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "", WS_CHILD |
+ LVS_REPORT | LVS_NOSORTHEADER | LVS_SHOWSELALWAYS | WS_TABSTOP |
+ LVS_SINGLESEL | WS_CLIPSIBLINGS,
+ 12, 25, 300, 300, MainWindow, NULL, Instance, NULL);
+ ListView_SetExtendedListViewStyle(IoList, LVS_EX_FULLROWSELECT);
+
+ int typeWidth = 85;
+ int pinWidth = 100;
+ int portWidth = 90;
+
+ LV_ADD_COLUMN(IoList, LV_IO_NAME, 250, _("Name"));
+ LV_ADD_COLUMN(IoList, LV_IO_TYPE, typeWidth, _("Type"));
+ LV_ADD_COLUMN(IoList, LV_IO_STATE, 100, _("State"));
+ LV_ADD_COLUMN(IoList, LV_IO_PIN, pinWidth, _("Pin on Processor"));
+ LV_ADD_COLUMN(IoList, LV_IO_PORT, portWidth, _("MCU Port"));
+
+ HorizScrollBar = CreateWindowEx(0, WC_SCROLLBAR, "", WS_CHILD |
+ SBS_HORZ | SBS_BOTTOMALIGN | WS_VISIBLE | WS_CLIPSIBLINGS,
+ 100, 100, 100, 100, MainWindow, NULL, Instance, NULL);
+ VertScrollBar = CreateWindowEx(0, WC_SCROLLBAR, "", WS_CHILD |
+ SBS_VERT | SBS_LEFTALIGN | WS_VISIBLE | WS_CLIPSIBLINGS,
+ 200, 100, 100, 100, MainWindow, NULL, Instance, NULL);
+ RECT scroll;
+ GetWindowRect(HorizScrollBar, &scroll);
+ ScrollHeight = scroll.bottom - scroll.top;
+ GetWindowRect(VertScrollBar, &scroll);
+ ScrollWidth = scroll.right - scroll.left;
+
+ StatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
+ "LDmicro started", MainWindow, 0);
+ int edges[] = { 250, 370, -1 };
+ SendMessage(StatusBar, SB_SETPARTS, 3, (LPARAM)edges);
+
+ ShowWindow(IoList, SW_SHOW);
+}
+
+//-----------------------------------------------------------------------------
+// Set up the title bar text for the main window; indicate whether we are in
+// simulation or editing mode, and indicate the filename.
+//-----------------------------------------------------------------------------
+void UpdateMainWindowTitleBar(void)
+{
+ char line[MAX_PATH+100];
+ if(InSimulationMode) {
+ if(RealTimeSimulationRunning) {
+ strcpy(line, _("LDmicro - Simulation (Running)"));
+ } else {
+ strcpy(line, _("LDmicro - Simulation (Stopped)"));
+ }
+ } else {
+ strcpy(line, _("LDmicro - Program Editor"));
+ }
+ if(strlen(CurrentSaveFile) > 0) {
+ sprintf(line+strlen(line), " - %s", CurrentSaveFile);
+ } else {
+ strcat(line, _(" - (not yet saved)"));
+ }
+
+ SetWindowText(MainWindow, line);
+}
+
+//-----------------------------------------------------------------------------
+// Set the enabled state of the logic menu items to reflect where we are on
+// the schematic (e.g. can't insert two coils in series).
+//-----------------------------------------------------------------------------
+void SetMenusEnabled(BOOL canNegate, BOOL canNormal, BOOL canResetOnly,
+ BOOL canSetOnly, BOOL canDelete, BOOL canInsertEnd, BOOL canInsertOther,
+ BOOL canPushDown, BOOL canPushUp, BOOL canInsertComment)
+{
+ EnableMenuItem(EditMenu, MNU_PUSH_RUNG_UP,
+ canPushUp ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(EditMenu, MNU_PUSH_RUNG_DOWN,
+ canPushDown ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(EditMenu, MNU_DELETE_RUNG,
+ (Prog.numRungs > 1) ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(InstructionMenu, MNU_NEGATE,
+ canNegate ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(InstructionMenu, MNU_MAKE_NORMAL,
+ canNormal ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(InstructionMenu, MNU_MAKE_RESET_ONLY,
+ canResetOnly ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(InstructionMenu, MNU_MAKE_SET_ONLY,
+ canSetOnly ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(InstructionMenu, MNU_INSERT_COMMENT,
+ canInsertComment ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(EditMenu, MNU_DELETE_ELEMENT,
+ canDelete ? MF_ENABLED : MF_GRAYED);
+
+ int t;
+ t = canInsertEnd ? MF_ENABLED : MF_GRAYED;
+ EnableMenuItem(InstructionMenu, MNU_INSERT_COIL, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_RES, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_MOV, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_ADD, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_SUB, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_MUL, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_DIV, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_CTC, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_PERSIST, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_READ_ADC, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_SET_PWM, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_MASTER_RLY, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_SHIFT_REG, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_LUT, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_PWL, t);
+
+ t = canInsertOther ? MF_ENABLED : MF_GRAYED;
+ EnableMenuItem(InstructionMenu, MNU_INSERT_TON, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_TOF, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_OSR, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_OSF, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_RTO, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_CONTACTS, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_CTU, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_CTD, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_EQU, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_NEQ, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_GRT, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_GEQ, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_LES, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_LEQ, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_SHORT, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_OPEN, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_UART_SEND, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_UART_RECV, t);
+ EnableMenuItem(InstructionMenu, MNU_INSERT_FMTD_STR, t);
+}
+
+//-----------------------------------------------------------------------------
+// Set the enabled state of the undo/redo menus.
+//-----------------------------------------------------------------------------
+void SetUndoEnabled(BOOL undoEnabled, BOOL redoEnabled)
+{
+ EnableMenuItem(EditMenu, MNU_UNDO, undoEnabled ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(EditMenu, MNU_REDO, redoEnabled ? MF_ENABLED : MF_GRAYED);
+}
+
+//-----------------------------------------------------------------------------
+// Create the top-level menu bar for the main window. Mostly static, but we
+// create the "select processor" menu from the list in mcutable.h dynamically.
+//-----------------------------------------------------------------------------
+HMENU MakeMainWindowMenus(void)
+{
+ HMENU settings, compile, help;
+ int i;
+
+ FileMenu = CreatePopupMenu();
+ AppendMenu(FileMenu, MF_STRING, MNU_NEW, _("&New\tCtrl+N"));
+ AppendMenu(FileMenu, MF_STRING, MNU_OPEN, _("&Open...\tCtrl+O"));
+ AppendMenu(FileMenu, MF_STRING, MNU_SAVE, _("&Save\tCtrl+S"));
+ AppendMenu(FileMenu, MF_STRING, MNU_SAVE_AS,_("Save &As..."));
+ AppendMenu(FileMenu, MF_SEPARATOR,0, "");
+ AppendMenu(FileMenu, MF_STRING, MNU_EXPORT,
+ _("&Export As Text...\tCtrl+E"));
+ AppendMenu(FileMenu, MF_SEPARATOR,0, "");
+ AppendMenu(FileMenu, MF_STRING, MNU_EXIT, _("E&xit"));
+
+ EditMenu = CreatePopupMenu();
+ AppendMenu(EditMenu, MF_STRING, MNU_UNDO, _("&Undo\tCtrl+Z"));
+ AppendMenu(EditMenu, MF_STRING, MNU_REDO, _("&Redo\tCtrl+Y"));
+ AppendMenu(EditMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(EditMenu, MF_STRING, MNU_INSERT_RUNG_BEFORE,
+ _("Insert Rung &Before\tShift+6"));
+ AppendMenu(EditMenu, MF_STRING, MNU_INSERT_RUNG_AFTER,
+ _("Insert Rung &After\tShift+V"));
+ AppendMenu(EditMenu, MF_STRING, MNU_PUSH_RUNG_UP,
+ _("Move Selected Rung &Up\tShift+Up"));
+ AppendMenu(EditMenu, MF_STRING, MNU_PUSH_RUNG_DOWN,
+ _("Move Selected Rung &Down\tShift+Down"));
+ AppendMenu(EditMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(EditMenu, MF_STRING, MNU_DELETE_ELEMENT,
+ _("&Delete Selected Element\tDel"));
+ AppendMenu(EditMenu, MF_STRING, MNU_DELETE_RUNG,
+ _("D&elete Rung\tShift+Del"));
+
+ InstructionMenu = CreatePopupMenu();
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_COMMENT,
+ _("Insert Co&mment\t;"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_CONTACTS,
+ _("Insert &Contacts\tC"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_OSR,
+ _("Insert OSR (One Shot Rising)\t&/"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_OSF,
+ _("Insert OSF (One Shot Falling)\t&\\"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_TON,
+ _("Insert T&ON (Delayed Turn On)\tO"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_TOF,
+ _("Insert TO&F (Delayed Turn Off)\tF"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_RTO,
+ _("Insert R&TO (Retentive Delayed Turn On)\tT"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_CTU,
+ _("Insert CT&U (Count Up)\tU"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_CTD,
+ _("Insert CT&D (Count Down)\tI"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_CTC,
+ _("Insert CT&C (Count Circular)\tJ"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_EQU,
+ _("Insert EQU (Compare for Equals)\t="));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_NEQ,
+ _("Insert NEQ (Compare for Not Equals)"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_GRT,
+ _("Insert GRT (Compare for Greater Than)\t>"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_GEQ,
+ _("Insert GEQ (Compare for Greater Than or Equal)\t."));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_LES,
+ _("Insert LES (Compare for Less Than)\t<"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_LEQ,
+ _("Insert LEQ (Compare for Less Than or Equal)\t,"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_OPEN,
+ _("Insert Open-Circuit"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_SHORT,
+ _("Insert Short-Circuit"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_MASTER_RLY,
+ _("Insert Master Control Relay"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_COIL,
+ _("Insert Coi&l\tL"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_RES,
+ _("Insert R&ES (Counter/RTO Reset)\tE"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_MOV,
+ _("Insert MOV (Move)\tM"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_ADD,
+ _("Insert ADD (16-bit Integer Add)\t+"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_SUB,
+ _("Insert SUB (16-bit Integer Subtract)\t-"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_MUL,
+ _("Insert MUL (16-bit Integer Multiply)\t*"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_DIV,
+ _("Insert DIV (16-bit Integer Divide)\tD"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_SHIFT_REG,
+ _("Insert Shift Register"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_LUT,
+ _("Insert Look-Up Table"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_PWL,
+ _("Insert Piecewise Linear"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_FMTD_STR,
+ _("Insert Formatted String Over UART"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_UART_SEND,
+ _("Insert &UART Send"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_UART_RECV,
+ _("Insert &UART Receive"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_SET_PWM,
+ _("Insert Set PWM Output"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_READ_ADC,
+ _("Insert A/D Converter Read\tP"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_INSERT_PERSIST,
+ _("Insert Make Persistent"));
+ AppendMenu(InstructionMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(InstructionMenu, MF_STRING, MNU_MAKE_NORMAL,
+ _("Make Norm&al\tA"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_NEGATE,
+ _("Make &Negated\tN"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_MAKE_SET_ONLY,
+ _("Make &Set-Only\tS"));
+ AppendMenu(InstructionMenu, MF_STRING, MNU_MAKE_RESET_ONLY,
+ _("Make &Reset-Only\tR"));
+
+ settings = CreatePopupMenu();
+ AppendMenu(settings, MF_STRING, MNU_MCU_SETTINGS, _("&MCU Parameters..."));
+ ProcessorMenu = CreatePopupMenu();
+ for(i = 0; i < NUM_SUPPORTED_MCUS; i++) {
+ AppendMenu(ProcessorMenu, MF_STRING, MNU_PROCESSOR_0+i,
+ SupportedMcus[i].mcuName);
+ }
+ AppendMenu(ProcessorMenu, MF_STRING, MNU_PROCESSOR_0+i,
+ _("(no microcontroller)"));
+ AppendMenu(settings, MF_STRING | MF_POPUP, (UINT_PTR)ProcessorMenu,
+ _("&Microcontroller"));
+
+ SimulateMenu = CreatePopupMenu();
+ AppendMenu(SimulateMenu, MF_STRING, MNU_SIMULATION_MODE,
+ _("Si&mulation Mode\tCtrl+M"));
+ AppendMenu(SimulateMenu, MF_STRING | MF_GRAYED, MNU_START_SIMULATION,
+ _("Start &Real-Time Simulation\tCtrl+R"));
+ AppendMenu(SimulateMenu, MF_STRING | MF_GRAYED, MNU_STOP_SIMULATION,
+ _("&Halt Simulation\tCtrl+H"));
+ AppendMenu(SimulateMenu, MF_STRING | MF_GRAYED, MNU_SINGLE_CYCLE,
+ _("Single &Cycle\tSpace"));
+
+ compile = CreatePopupMenu();
+ AppendMenu(compile, MF_STRING, MNU_COMPILE, _("&Compile\tF5"));
+ AppendMenu(compile, MF_STRING, MNU_COMPILE_AS, _("Compile &As..."));
+
+ help = CreatePopupMenu();
+ AppendMenu(help, MF_STRING, MNU_MANUAL, _("&Manual...\tF1"));
+ AppendMenu(help, MF_STRING, MNU_ABOUT, _("&About..."));
+
+ TopMenu = CreateMenu();
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)FileMenu, _("&File"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)EditMenu, _("&Edit"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)settings,
+ _("&Settings"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)InstructionMenu,
+ _("&Instruction"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)SimulateMenu,
+ _("Si&mulate"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)compile,
+ _("&Compile"));
+ AppendMenu(TopMenu, MF_STRING | MF_POPUP, (UINT_PTR)help, _("&Help"));
+
+ return TopMenu;
+}
+
+//-----------------------------------------------------------------------------
+// Adjust the size and visibility of the scrollbars as necessary, either due
+// to a change in the size of the program or a change in the size of the
+// window.
+//-----------------------------------------------------------------------------
+void RefreshScrollbars(void)
+{
+ SCROLLINFO vert, horiz;
+ SetUpScrollbars(&NeedHoriz, &horiz, &vert);
+ SetScrollInfo(HorizScrollBar, SB_CTL, &horiz, TRUE);
+ SetScrollInfo(VertScrollBar, SB_CTL, &vert, TRUE);
+
+ RECT main;
+ GetClientRect(MainWindow, &main);
+
+ if(NeedHoriz) {
+ MoveWindow(HorizScrollBar, 0, IoListTop - ScrollHeight - 2,
+ main.right - ScrollWidth - 2, ScrollHeight, TRUE);
+ ShowWindow(HorizScrollBar, SW_SHOW);
+ EnableWindow(HorizScrollBar, TRUE);
+ } else {
+ ShowWindow(HorizScrollBar, SW_HIDE);
+ }
+ MoveWindow(VertScrollBar, main.right - ScrollWidth - 2, 1, ScrollWidth,
+ NeedHoriz ? (IoListTop - ScrollHeight - 4) : (IoListTop - 3), TRUE);
+
+ MoveWindow(VertScrollBar, main.right - ScrollWidth - 2, 1, ScrollWidth,
+ NeedHoriz ? (IoListTop - ScrollHeight - 4) : (IoListTop - 3), TRUE);
+
+ InvalidateRect(MainWindow, NULL, FALSE);
+}
+
+//-----------------------------------------------------------------------------
+// Respond to a WM_VSCROLL sent to the main window, presumably by the one and
+// only vertical scrollbar that it has as a child.
+//-----------------------------------------------------------------------------
+void VscrollProc(WPARAM wParam)
+{
+ int prevY = ScrollYOffset;
+ switch(LOWORD(wParam)) {
+ case SB_LINEUP:
+ case SB_PAGEUP:
+ if(ScrollYOffset > 0) {
+ ScrollYOffset--;
+ }
+ break;
+
+ case SB_LINEDOWN:
+ case SB_PAGEDOWN:
+ if(ScrollYOffset < ScrollYOffsetMax) {
+ ScrollYOffset++;
+ }
+ break;
+
+ case SB_TOP:
+ ScrollYOffset = 0;
+ break;
+
+ case SB_BOTTOM:
+ ScrollYOffset = ScrollYOffsetMax;
+ break;
+
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ ScrollYOffset = HIWORD(wParam);
+ break;
+ }
+ if(prevY != ScrollYOffset) {
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = ScrollYOffset;
+ SetScrollInfo(VertScrollBar, SB_CTL, &si, TRUE);
+
+ InvalidateRect(MainWindow, NULL, FALSE);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Respond to a WM_HSCROLL sent to the main window, presumably by the one and
+// only horizontal scrollbar that it has as a child.
+//-----------------------------------------------------------------------------
+void HscrollProc(WPARAM wParam)
+{
+ int prevX = ScrollXOffset;
+ switch(LOWORD(wParam)) {
+ case SB_LINEUP:
+ ScrollXOffset -= FONT_WIDTH;
+ break;
+
+ case SB_PAGEUP:
+ ScrollXOffset -= POS_WIDTH*FONT_WIDTH;
+ break;
+
+ case SB_LINEDOWN:
+ ScrollXOffset += FONT_WIDTH;
+ break;
+
+ case SB_PAGEDOWN:
+ ScrollXOffset += POS_WIDTH*FONT_WIDTH;
+ break;
+
+ case SB_TOP:
+ ScrollXOffset = 0;
+ break;
+
+ case SB_BOTTOM:
+ ScrollXOffset = ScrollXOffsetMax;
+ break;
+
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ ScrollXOffset = HIWORD(wParam);
+ break;
+ }
+
+ if(ScrollXOffset > ScrollXOffsetMax) ScrollXOffset = ScrollXOffsetMax;
+ if(ScrollXOffset < 0) ScrollXOffset = 0;
+
+ if(prevX != ScrollXOffset) {
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = ScrollXOffset;
+ SetScrollInfo(HorizScrollBar, SB_CTL, &si, TRUE);
+
+ InvalidateRect(MainWindow, NULL, FALSE);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Cause the status bar and the list view to be in sync with the actual data
+// structures describing the settings and the I/O configuration. Listview
+// does callbacks to get the strings it displays, so it just needs to know
+// how many elements to populate.
+//-----------------------------------------------------------------------------
+void RefreshControlsToSettings(void)
+{
+ int i;
+
+ if(!IoListOutOfSync) {
+ IoListSelectionPoint = -1;
+ for(i = 0; i < Prog.io.count; i++) {
+ if(ListView_GetItemState(IoList, i, LVIS_SELECTED)) {
+ IoListSelectionPoint = i;
+ break;
+ }
+ }
+ }
+
+ ListView_DeleteAllItems(IoList);
+ for(i = 0; i < Prog.io.count; i++) {
+ LVITEM lvi;
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.state = lvi.stateMask = 0;
+ lvi.iItem = i;
+ lvi.iSubItem = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = i;
+
+ if(ListView_InsertItem(IoList, &lvi) < 0) oops();
+ }
+ if(IoListSelectionPoint >= 0) {
+ for(i = 0; i < Prog.io.count; i++) {
+ ListView_SetItemState(IoList, i, 0, LVIS_SELECTED);
+ }
+ ListView_SetItemState(IoList, IoListSelectionPoint, LVIS_SELECTED,
+ LVIS_SELECTED);
+ ListView_EnsureVisible(IoList, IoListSelectionPoint, FALSE);
+ }
+ IoListOutOfSync = FALSE;
+
+ if(Prog.mcu) {
+ SendMessage(StatusBar, SB_SETTEXT, 0, (LPARAM)Prog.mcu->mcuName);
+ } else {
+ SendMessage(StatusBar, SB_SETTEXT, 0, (LPARAM)_("no MCU selected"));
+ }
+ char buf[256];
+ sprintf(buf, _("cycle time %.2f ms"), (double)Prog.cycleTime/1000.0);
+ SendMessage(StatusBar, SB_SETTEXT, 1, (LPARAM)buf);
+
+ if(Prog.mcu && (Prog.mcu->whichIsa == ISA_ANSIC ||
+ Prog.mcu->whichIsa == ISA_INTERPRETED))
+ {
+ strcpy(buf, "");
+ } else {
+ sprintf(buf, _("processor clock %.4f MHz"),
+ (double)Prog.mcuClock/1000000.0);
+ }
+ SendMessage(StatusBar, SB_SETTEXT, 2, (LPARAM)buf);
+
+ for(i = 0; i < NUM_SUPPORTED_MCUS; i++) {
+ if(&SupportedMcus[i] == Prog.mcu) {
+ CheckMenuItem(ProcessorMenu, MNU_PROCESSOR_0+i, MF_CHECKED);
+ } else {
+ CheckMenuItem(ProcessorMenu, MNU_PROCESSOR_0+i, MF_UNCHECKED);
+ }
+ }
+ // `(no microcontroller)' setting
+ if(!Prog.mcu) {
+ CheckMenuItem(ProcessorMenu, MNU_PROCESSOR_0+i, MF_CHECKED);
+ } else {
+ CheckMenuItem(ProcessorMenu, MNU_PROCESSOR_0+i, MF_UNCHECKED);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Regenerate the I/O list, keeping the selection in the same place if
+// possible.
+//-----------------------------------------------------------------------------
+void GenerateIoListDontLoseSelection(void)
+{
+ int i;
+ IoListSelectionPoint = -1;
+ for(i = 0; i < Prog.io.count; i++) {
+ if(ListView_GetItemState(IoList, i, LVIS_SELECTED)) {
+ IoListSelectionPoint = i;
+ break;
+ }
+ }
+ IoListSelectionPoint = GenerateIoList(IoListSelectionPoint);
+ // can't just update the listview index; if I/O has been added then the
+ // new selection point might be out of range till we refill it
+ IoListOutOfSync = TRUE;
+ RefreshControlsToSettings();
+}
+
+//-----------------------------------------------------------------------------
+// Called when the main window has been resized. Adjust the size of the
+// status bar and the listview to reflect the new window size.
+//-----------------------------------------------------------------------------
+void MainWindowResized(void)
+{
+ RECT main;
+ GetClientRect(MainWindow, &main);
+
+ RECT status;
+ GetWindowRect(StatusBar, &status);
+ int statusHeight = status.bottom - status.top;
+
+ MoveWindow(StatusBar, 0, main.bottom - statusHeight, main.right,
+ statusHeight, TRUE);
+
+ // Make sure that the I/O list can't disappear entirely.
+ if(IoListHeight < 30) {
+ IoListHeight = 30;
+ }
+ IoListTop = main.bottom - IoListHeight - statusHeight;
+ // Make sure that we can't drag the top of the I/O list above the
+ // bottom of the menu bar, because it then becomes inaccessible.
+ if(IoListTop < 5) {
+ IoListHeight = main.bottom - statusHeight - 5;
+ IoListTop = main.bottom - IoListHeight - statusHeight;
+ }
+ MoveWindow(IoList, 0, IoListTop, main.right, IoListHeight, TRUE);
+
+ RefreshScrollbars();
+
+ InvalidateRect(MainWindow, NULL, FALSE);
+}
+
+//-----------------------------------------------------------------------------
+// Toggle whether we are in simulation mode. A lot of options are only
+// available in one mode or the other.
+//-----------------------------------------------------------------------------
+void ToggleSimulationMode(void)
+{
+ InSimulationMode = !InSimulationMode;
+
+ if(InSimulationMode) {
+ EnableMenuItem(SimulateMenu, MNU_START_SIMULATION, MF_ENABLED);
+ EnableMenuItem(SimulateMenu, MNU_SINGLE_CYCLE, MF_ENABLED);
+
+ EnableMenuItem(FileMenu, MNU_OPEN, MF_GRAYED);
+ EnableMenuItem(FileMenu, MNU_SAVE, MF_GRAYED);
+ EnableMenuItem(FileMenu, MNU_SAVE_AS, MF_GRAYED);
+ EnableMenuItem(FileMenu, MNU_NEW, MF_GRAYED);
+ EnableMenuItem(FileMenu, MNU_EXPORT, MF_GRAYED);
+
+ EnableMenuItem(TopMenu, 1, MF_GRAYED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 2, MF_GRAYED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 3, MF_GRAYED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 5, MF_GRAYED | MF_BYPOSITION);
+
+ CheckMenuItem(SimulateMenu, MNU_SIMULATION_MODE, MF_CHECKED);
+
+ ClearSimulationData();
+ // Recheck InSimulationMode, because there could have been a compile
+ // error, which would have kicked us out of simulation mode.
+ if(UartFunctionUsed() && InSimulationMode) {
+ ShowUartSimulationWindow();
+ }
+ } else {
+ RealTimeSimulationRunning = FALSE;
+ KillTimer(MainWindow, TIMER_SIMULATE);
+
+ EnableMenuItem(SimulateMenu, MNU_START_SIMULATION, MF_GRAYED);
+ EnableMenuItem(SimulateMenu, MNU_STOP_SIMULATION, MF_GRAYED);
+ EnableMenuItem(SimulateMenu, MNU_SINGLE_CYCLE, MF_GRAYED);
+
+ EnableMenuItem(FileMenu, MNU_OPEN, MF_ENABLED);
+ EnableMenuItem(FileMenu, MNU_SAVE, MF_ENABLED);
+ EnableMenuItem(FileMenu, MNU_SAVE_AS, MF_ENABLED);
+ EnableMenuItem(FileMenu, MNU_NEW, MF_ENABLED);
+ EnableMenuItem(FileMenu, MNU_EXPORT, MF_ENABLED);
+
+ EnableMenuItem(TopMenu, 1, MF_ENABLED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 2, MF_ENABLED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 3, MF_ENABLED | MF_BYPOSITION);
+ EnableMenuItem(TopMenu, 5, MF_ENABLED | MF_BYPOSITION);
+
+ CheckMenuItem(SimulateMenu, MNU_SIMULATION_MODE, MF_UNCHECKED);
+
+ if(UartFunctionUsed()) {
+ DestroyUartSimulationWindow();
+ }
+ }
+
+ UpdateMainWindowTitleBar();
+
+ DrawMenuBar(MainWindow);
+ InvalidateRect(MainWindow, NULL, FALSE);
+ ListView_RedrawItems(IoList, 0, Prog.io.count - 1);
+}
+
+//-----------------------------------------------------------------------------
+// Start real-time simulation. Have to update the controls grayed status
+// to reflect this.
+//-----------------------------------------------------------------------------
+void StartSimulation(void)
+{
+ RealTimeSimulationRunning = TRUE;
+
+ EnableMenuItem(SimulateMenu, MNU_START_SIMULATION, MF_GRAYED);
+ EnableMenuItem(SimulateMenu, MNU_STOP_SIMULATION, MF_ENABLED);
+ StartSimulationTimer();
+
+ UpdateMainWindowTitleBar();
+}
+
+//-----------------------------------------------------------------------------
+// Stop real-time simulation. Have to update the controls grayed status
+// to reflect this.
+//-----------------------------------------------------------------------------
+void StopSimulation(void)
+{
+ RealTimeSimulationRunning = FALSE;
+
+ EnableMenuItem(SimulateMenu, MNU_START_SIMULATION, MF_ENABLED);
+ EnableMenuItem(SimulateMenu, MNU_STOP_SIMULATION, MF_GRAYED);
+ KillTimer(MainWindow, TIMER_SIMULATE);
+
+ UpdateMainWindowTitleBar();
+}
|