/* * This file handles all of the user interface issues for * the MediaView sample browser. */ #include #include #include #include #include #include #include #include #include "ctl3d.h" /* MediaView Include Files */ #include #include /* Application Include Files */ #include "mvui.h" #include "view.h" #include "resrc1.h" #include "proto.h" /* * This applicaton keeps around 1 view (window with scrolling and * non-scrolling regions. The source view shows how to have * a second title open (with a View into it). This only works for * the USA.M12 title, which has a companion title SOURCES.M12. */ VIEW View = {0}; VIEW SourceView = {0}; APPVIEW AppView = {0}; int bShowHotspots = FALSE; int iKerningBoundary = 0; HANDLE hAccTable = 0; /* handle to accelerator table */ HWND hMainWnd = 0; /* handle to main window */ HWND hFP = 0; /* face plate for Views */ /* the source window (specific to the USA title */ HWND hSourceWnd; /* the source display window */ LPSTR szSourceTitle = "SOURCES.M12"; LPSTR szUSATitle = "USA.M12"; /* list of menu items that are grayed on entry, then enabled at file open */ int MenuItems[] = { ID_FILE_PRINTTOPIC, ID_FILE_PRINTMARKED, ID_FILE_PRINTALLTOPICS, ID_EDIT_COPYTOPIC, ID_EDIT_COPYSELECTION, ID_EDIT_SEARCH, ID_EDIT_CHARACTERSTYLES, ID_BOOKMARK_DEFINE, ID_TOPIC_CONTENTS, ID_TOPIC_BACK, ID_TOPIC_NEXT, ID_TOPIC_PREV, ID_TOPIC_INDEX, ID_TOPIC_MARK, ID_VIEW_HIGHLIGHTS, ID_VIEW_SEARCHRESULTS, ID_VIEW_SOURCE, ID_VIEW_HOTSPOTS, ID_EFFECTS_TEXTCOLOR, ID_EFFECTS_HITCOLOR, ID_OPTIONS_MAGNIFYTEXT, }; /* variables for GetOpenFilename commmon dialog */ OPENFILENAME ofn = {0}; char szFilterSpec [128] = /* file type filters */ "MediaView 1.2 (*.M12)\0*.M12\0All Files (*.*)\0*.*\0"; /* variables for the Print common dialog */ PRINTDLG pd = {0}; /* variables for ChooseColor common dialog */ CHOOSECOLOR cc = {0}; COLORREF aclrCust[16] = {0}; char szFileName[_MAX_PATH] = {0}; char szFileTitle[_MAX_PATH] = {0}; char szWindowTitle[] = "MediaView Browser"; /* cursors for different hotspot types */ HCURSOR curT = 0; HCURSOR curB = 0; HCURSOR curE = 0; HCURSOR curU = 0; HCURSOR curArrow = 0; HCURSOR curIbeam = 0; /**************************************************************************** ** FUNCTION: WinMain ** ** PURPOSE: initialize and call do main processing loop ** ** COMMENTS: ** ****************************************************************************/ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; int argc, ret = TRUE; LPSTR argv[10]; /* Enable the 3-D controls */ Ctl3dRegister(hInstance); Ctl3dAutoSubclass(hInstance); argc = UI_ParseCmdLine(lpCmdLine, argv, DIMENSION(argv)); /* was there a flag for setting the KerningBoundary? */ if (argc != 0 && _fstrnicmp(argv[0], "/kern=", 6) == 0) { iKerningBoundary = atoi(argv[0]+6); argv[0] = argv[1]; --argc; } if (!hPrevInstance) if (!InitApplication(hInstance)) { ret = FALSE; goto exit; } if (!InitInstance(hInstance, nCmdShow)) { ret = FALSE; goto exit; } /* Create a View. Other applications may want to create multiple Views */ if (!View_Create(&View, hMainWnd, hFP, hInstance)) { ret = FALSE; goto exit; } /* create a second view ... this one will show the SOURCES for the USA title */ hSourceWnd = CreateDialog(hInstance, "SourceDlg", hMainWnd, (DLGPROC)SourceDlgProc); ShowWindow(hSourceWnd, SW_HIDE); View_Create(&SourceView, hMainWnd, hSourceWnd, hInstance); /* set up both the View and SourceView to reference the same AppView */ View.lpApp = &AppView; SourceView.lpApp = &AppView; AppView.hMain = hMainWnd; /* do initial sizing of faceplate and source window */ UI_ResizeFacePlate(hMainWnd, hFP, View.hView); UI_SizeViewInWindow(hSourceWnd, IDC_STATIC, SourceView.hView, 2); /* everything is set up, show the main window */ ShowWindow(hMainWnd, SW_SHOW); /* was there a filename on the command line? */ if (argc > 0) UI_OpenFile(argv[0]); /* the main message loop */ while (GetMessage(&msg, 0, 0, 0)) { /* modless dialog boxes need custom dispatching */ if (View.lpApp->hSearch && IsDialogMessage(View.lpApp->hSearch, &msg)) continue; if (View.lpApp->hHist && IsDialogMessage(View.lpApp->hHist, &msg)) continue; /* otherwise, dispatch to the main message pump */ else if (!TranslateAccelerator(hMainWnd, hAccTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } ret = msg.wParam; exit: /* clean up the 3 -D controls */ Ctl3dUnregister(hInstance); return(ret); } /**************************************************************************** ** FUNCTION: InitApplication ** ** PURPOSE: initialize window data and registers window class ** ** COMMENTS: ** ****************************************************************************/ BOOL InitApplication(HANDLE hInstance) { WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (hInstance, "myicon"); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MVAppMenu"; wc.lpszClassName = "MVAppClass"; if (RegisterClass(&wc) == 0) return(FALSE); if (!View_Register(hInstance)) return(FALSE); if (!Pane_Register(hInstance)) return(FALSE); return(TRUE); } /**************************************************************************** ** FUNCTION: InitInstance ** ** PURPOSE: create the windows and create the button bar ** ** COMMENTS: ** ****************************************************************************/ BOOL InitInstance(HANDLE hInstance, int nCmdShow) { int i; hAccTable = LoadAccelerators(hInstance, "MVAppAccelerators"); /* create the main application window */ hMainWnd = CreateWindow( "MVAppClass", szWindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0 ); if (!hMainWnd) return (FALSE); ShowWindow(hMainWnd, SW_HIDE); /* grey out the portions of the menu that need an open file */ UI_EnableMenuItems(hMainWnd, MenuItems, DIMENSION(MenuItems), MF_GRAYED|MF_BYCOMMAND); UpdateWindow(hMainWnd); /* manifest the button bar */ if ((hFP = CreateDialog(hInstance, "FacePlateDlg", hMainWnd, (DLGPROC)FacePlateDlgProc)) == 0) return(FALSE); /* fill in non-variant fields of OPENFILENAME struct. */ ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hMainWnd; ofn.lpstrFilter = szFilterSpec; ofn.lpstrCustomFilter = 0; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = szFileName; ofn.nMaxFile = sizeof(szFileName); ofn.lpstrInitialDir = 0; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrTitle = 0; ofn.lpstrDefExt = "TXT"; ofn.Flags = OFN_HIDEREADONLY; /* initialize the PRINTDLG structure */ _fmemset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.hwndOwner = hMainWnd; pd.Flags = PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS; /* initialize the CHOOSECOLOR structure */ for (i = 0; i < 16; i++) { /* Set the custom color controls to white. */ aclrCust[i] = RGB(255, 255, 255); } cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndOwner = hMainWnd; cc.rgbResult = RGB(0, 0, 0); cc.lpCustColors = aclrCust; cc.Flags = CC_PREVENTFULLOPEN; UI_InitCursors(hInstance); return (TRUE); } /**************************************************************************** ** FUNCTION: MainWndProc ** ** PURPOSE: Handle top level messages to the main window ** ** COMMENTS: ** ****************************************************************************/ long WINAPI MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam) { int state; UINT cmd; HINSTANCE hInst = (HINSTANCE)GetWindowWord(hWnd, GWW_HINSTANCE); switch (message) { case WM_KEYDOWN: /* if there are multiple Views, the application needs to * determine which View's Pane has the focus and pass * the message to the proper View. This example only has * one View, so it's easy. */ View_KeyDown(&View, GetFocus(), wParam, lParam); break; case WM_SIZE: UI_ResizeFacePlate(hWnd, hFP, View.hView); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case ID_FILE_OPEN: /* call the common dialog to get a file name */ if (!GetOpenFileName ((LPOPENFILENAME)&ofn)) break; UI_OpenFile(ofn.lpstrFile); break; case ID_FILE_PRINTTOPIC: if (PrintDlg(&pd) == 0) break; if (MV_PrintTopic(&View, pd.hDC) != 0) ErrorMsg("Print topic failed", "error"); break; case ID_FILE_PRINTMARKED: if (PrintDlg(&pd) == 0) break; if (MV_PrintMarkList(&View, pd.hDC) != 0) ErrorMsg("Print marked topics failed", "error"); break; case ID_FILE_PRINTALLTOPICS: if (PrintDlg(&pd) == 0) break; if (MV_PrintAll(&View, pd.hDC) != 0) ErrorMsg("Print all failed", "error"); break; case ID_FILE_EXIT: DestroyWindow(hWnd); break; case ID_EDIT_COPYTOPIC: View_CopyTopic(&View); break; case ID_EDIT_COPYSELECTION: View_CopySelection(&View); break; case ID_EDIT_SEARCH: DialogBox(hInst, "SearchDlg", hWnd, SearchDlgProc); break; case ID_EDIT_CHARACTERSTYLES: DialogBox(hInst, "CharStylesDlg", hWnd, CharStylesDlgProc); break; case ID_BOOKMARK_DEFINE: DialogBox(hInst, "BookmarkDlg", hWnd, BookmarkDlgProc); break; case ID_TOPIC_CONTENTS: View_Contents(&View); break; case ID_TOPIC_INDEX: DialogBox(hInst, "IndexDlg", hWnd, IndexDlgProc); break; case ID_TOPIC_HISTORY: if (View.lpApp->hHist == 0) View.lpApp->hHist = CreateDialog(hInst, "HistoryDlg", hWnd, HistoryDlgProc); BringWindowToTop(View.lpApp->hHist); break; case ID_TOPIC_BACK: MV_Back(&View); break; case ID_TOPIC_NEXT: View_NextPrev(&View, IDC_NEXT); break; case ID_TOPIC_PREV: View_NextPrev(&View, IDC_PREV); break; case ID_TOPIC_MARK: DialogBox(hInst, "MarkDlg", hWnd, MarkDlgProc); break; case ID_VIEW_HIGHLIGHTS: View.showHits = UI_ToggleMenuItem(hWnd, ID_VIEW_HIGHLIGHTS); View_Layout(&View); break; case ID_VIEW_SEARCHRESULTS: state = UI_ToggleMenuItem(hWnd, ID_VIEW_SEARCHRESULTS); if (state == MF_CHECKED) { /* Create the Search Results display window */ CreateDialog(hInst, "SearchResultsDlg", hMainWnd, (DLGPROC)SearchResultsDlgProc); BringWindowToTop(View.lpApp->hSearch); } else { /* close the Search Results window */ SendMessage(View.lpApp->hSearch, WM_CLOSE, 0, 0); } break; case ID_VIEW_SOURCE: /* view the USA sources window */ state = UI_ToggleMenuItem(hWnd, ID_VIEW_SOURCE); if (state == MF_CHECKED) { ShowWindow(hSourceWnd, SW_SHOW); View.lpApp->showSource = TRUE; /* set the title of the window to the Title name */ if (View.isOpen) MV_SourceUpdate(View_ValidMV(&View)); } else { /* hide the Source window */ ShowWindow(hSourceWnd, SW_HIDE); View.lpApp->showSource = FALSE; } break; case ID_VIEW_HOTSPOTS: bShowHotspots = UI_ToggleMenuItem(hWnd, ID_VIEW_HOTSPOTS); View_HotspotHighlights(&View, bShowHotspots == MF_CHECKED); break; case ID_EFFECTS_TEXTCOLOR: if (ChooseColor(&cc)) View_TextColor(&View, cc.rgbResult); break; case ID_EFFECTS_HITCOLOR: if (ChooseColor(&cc)) { DeleteObject(View.hHitBrush); View.hHitBrush = CreateSolidBrush(cc.rgbResult); if (View.showHits) View_Layout(&View); } break; case ID_OPTIONS_MAGNIFYTEXT: DialogBox(hInst, "MagnifyDlg", hWnd, MagnifyDlgProc); break; case ID_HELP_ABOUT: DialogBox(hInst, "AboutDlg", hWnd, AboutDlgProc); break; default: /* these menu items are added dynamically */ if (wParam >= ID_BOOKMARKBASE && wParam < ID_BOOKMARKBASE + NUMBOOKMARKS) { MV_GoToFromBookmark(&View, wParam); break; } } break; case WM_DESTROY: View_Close(&View); UI_DeleteCursors(); PostQuitMessage(0); break; default: /* otherwise ... */ return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); } /**************************************************************************** ** FUNCTION: UI_ResizeFacePlate ** ** PURPOSE: Respond to size changes in the parent and resize the ** ** FacePlate. This includes resizing the View display window. ** ** COMMENTS: ** ****************************************************************************/ void UI_ResizeFacePlate(HWND hMain, HWND hFP, HWND hView) { RECT rect; int x, y; /* size the whole face plate */ GetClientRect(hMain, &rect); x = rect.right - rect.left; y = rect.bottom - rect.top; MoveWindow(hFP, 0, 0, x, y, TRUE); /* size the View display frame */ #define FRAME 20 GetClientRect(GetDlgItem(hFP, IDC_CONTENTS), &rect); MoveWindow(GetDlgItem(hFP, IDC_STATIC), FRAME, rect.bottom + FRAME, x - 2*FRAME, y - 2*FRAME - rect.bottom, TRUE); InvalidateRect(hFP, 0, TRUE); /* size the View with a 2 pixel border inside the faceplate window */ UI_SizeViewInWindow(hFP, IDC_STATIC, hView, 2); } /**************************************************************************** ** FUNCTION: UI_SizeViewInWindow ** ** PURPOSE: Size the View into a particular control in a window. ** ** COMMENTS: ** ** The border allows the View to have a margin inside the control. ** ****************************************************************************/ void UI_SizeViewInWindow(HWND hWnd, int control, HWND hView, int border) { RECT rect; POINT pt; /* now size the View itself within the display frame */ GetWindowRect(GetDlgItem(hWnd, control), &rect); pt.x = rect.left; pt.y = rect.top; ScreenToClient(hWnd, &pt); /* these force the layout and then the painting of the View */ MoveWindow(hView, pt.x+border, pt.y+border, rect.right - rect.left-2*border, rect.bottom - rect.top-2*border, TRUE); InvalidateRect(hView, 0, TRUE); } /**************************************************************************** ** FUNCTION: FacePlateDlgProc ** ** PURPOSE: Dispatch the buttons from the button bar ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI FacePlateDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UINT cmd; switch (message) { case WM_INITDIALOG: UI_EnableControls(hDlg, FALSE, IDC_CONTENTS, IDC_INDEX, IDC_BACK, IDC_HISTORY, IDC_NEXT, IDC_PREV, IDC_SEARCH, 0); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_CONTENTS: SendMessage(hMainWnd, WM_COMMAND, ID_TOPIC_CONTENTS, 0); break; case IDC_INDEX: SendMessage(hMainWnd, WM_COMMAND, ID_TOPIC_INDEX, 0); break; case IDC_BACK: MV_Back(&View); break; case IDC_HISTORY: SendMessage(hMainWnd, WM_COMMAND, ID_TOPIC_HISTORY, 0); break; case IDC_NEXT: SendMessage(hMainWnd, WM_COMMAND, ID_TOPIC_NEXT, 0); break; case IDC_PREV: SendMessage(hMainWnd, WM_COMMAND, ID_TOPIC_PREV, 0); break; case IDC_SEARCH: SendMessage(hMainWnd, WM_COMMAND, ID_EDIT_SEARCH, 0); break; } /* * After a button is processed, put the focus back on the main * window so that keystrokes will all be routed there. */ SetFocus(hMainWnd); break; } return (FALSE); } /**************************************************************************** ** FUNCTION: AboutDlgProc ** ** PURPOSE: About box handling ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UINT cmd; switch (message) { case WM_INITDIALOG: SetFocus(hDlg); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDOK: EndDialog(hDlg, TRUE); return(TRUE); } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: SearchDlgProc ** ** PURPOSE: Full Text Search ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI SearchDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { int scope; char ** groupList; HCURSOR hcurOld; int andFlag; int err; static char szSearch[512] = {0}; LPGROUPUI lpGroup; UINT cmd; switch (message) { case WM_INITDIALOG: /* initialize to All Topics radio button */ SendDlgItemMessage( hDlg, IDC_ALL, BM_SETCHECK, 1, 0); SetFocus(GetDlgItem(hDlg, IDC_SEARCH)); /* load up the Groups list (initially disabled) */ EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), FALSE); lpGroup = View.lpGroups; while (lpGroup && lpGroup->title) { SendDlgItemMessage(hDlg, IDC_GROUPLIST, LB_ADDSTRING, 0, (LPARAM)(LPSTR)lpGroup->title); ++lpGroup; } /* initialize to the previous search word */ SendDlgItemMessage(hDlg, IDC_SEARCH, WM_SETTEXT, 0, (LPARAM)(LPSTR)szSearch); SendDlgItemMessage(hDlg, IDC_SEARCH, EM_SETSEL, 0, MAKELPARAM(0, strlen(szSearch))); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDOK: /* set up for the search */ groupList = 0; hcurOld = SetCursor(LoadCursor(0, IDC_WAIT)); /* which radio button is down? */ if (SendDlgItemMessage( hDlg, IDC_TOPIC, BM_GETCHECK, 0, 0)) scope = SEARCH_TOPIC; if (SendDlgItemMessage( hDlg, IDC_GROUPS, BM_GETCHECK, 0, 0)) { groupList = UI_GetGroups(hDlg, &View); scope = SEARCH_GROUPS; } if (SendDlgItemMessage( hDlg, IDC_ALL, BM_GETCHECK, 0, 0)) scope = SEARCH_ALL; /* is this an AND or an OR of the search words? */ if (SendDlgItemMessage( hDlg, IDC_AND, BM_GETCHECK, 0, 0)) andFlag = TRUE; else andFlag = FALSE; /* get the search string and submit the query */ SendDlgItemMessage(hDlg, IDC_SEARCH, WM_GETTEXT, sizeof(szSearch), (LPARAM)(LPSTR)szSearch); err = MV_Search(&View, scope, andFlag, groupList, szSearch); if (groupList) GlobalFreePtr(groupList); SetCursor(hcurOld); /* if any were found, put up the search results Dialog */ if (err == 0) { /* make sure that the Search Results display is visible */ if (!View.lpApp->hSearch) SendMessage(View.lpApp->hMain, WM_COMMAND, ID_VIEW_SEARCHRESULTS, 0); MV_ShowSearchResults(&View); } else if (err == ERR_FAILED) { ErrorMsg("No matches", "Search Results"); break; } else { /* use MediaView to get error string */ QueryGetErrorMessage(err, szSearch, sizeof(szSearch)); ErrorMsg(szSearch, "Search Results"); break; } /* show the highlights if the flag is set */ if (View.showHits) View_Layout(&View); EndDialog(hDlg, TRUE); return(TRUE); case IDCANCEL: EndDialog(hDlg, FALSE); return(TRUE); break; case IDC_TOPIC: /* current topic */ EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), FALSE); break; case IDC_GROUPS: /* topics in group */ EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), TRUE); break; case IDC_ALL: /* all topics */ EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), FALSE); break; } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: CharStylesDlgProc ** ** PURPOSE: Display/Format character styles ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI CharStylesDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UINT cmd; switch (message) { case WM_INITDIALOG: View_GetCharStyles(&View, GetDlgItem(hDlg, IDC_CHARSTYLES)); SendDlgItemMessage(hDlg, IDC_CHARSTYLES, LB_SETCURSEL, 0, 0); SetFocus(GetDlgItem(hDlg, IDC_CHARSTYLES)); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDCANCEL: EndDialog(hDlg, TRUE); return(TRUE); case IDC_FORMAT: /* common dialog for choosing a font */ if (View_SetCharStyles(&View, GetDlgItem(hDlg, IDC_CHARSTYLES)) == 0) EndDialog(hDlg, TRUE); return(TRUE); } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: BookmarkDlgProc ** ** PURPOSE: ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI BookmarkDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { int status; char buff[512]; UINT cmd; switch (message) { case WM_INITDIALOG: /* don't enable the "Add" button unless there is text */ EnableWindow(GetDlgItem(hDlg, IDC_ADD), FALSE); SetFocus(GetDlgItem(hDlg, IDC_BOOKMARK)); /* display existing bookmarks and init controls */ MV_ShowBookmarks(GetDlgItem(hDlg, IDC_LIST1), hMainWnd); UI_EnableBookmarkControls(hDlg); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_BOOKMARK: /* "Add" enabled as soon as there is text */ if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { status = (SendDlgItemMessage(hDlg, IDC_BOOKMARK, WM_GETTEXT, (WPARAM)(sizeof(buff)), (long)(LPSTR)buff) != 0); EnableWindow(GetDlgItem(hDlg, IDC_ADD), status); } break; case IDOK: EndDialog(hDlg, TRUE); return(TRUE); case IDC_ADD: SendDlgItemMessage(hDlg, IDC_BOOKMARK, WM_GETTEXT, (WPARAM)(sizeof(buff)), (long)(LPSTR)buff); if (!MV_AddBookmark(hMainWnd, &View, buff)) ErrorMsg("Too many bookmarks.", "Bookmarks"); MV_ShowBookmarks(GetDlgItem(hDlg, IDC_LIST1), hMainWnd); UI_EnableBookmarkControls(hDlg); break; case IDC_DELETE: MV_DelBookmark(GetDlgItem(hDlg, IDC_LIST1), hMainWnd); MV_ShowBookmarks(GetDlgItem(hDlg, IDC_LIST1), hMainWnd); UI_EnableBookmarkControls(hDlg); break; case IDC_LIST1: if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) UI_EnableBookmarkControls(hDlg); break; } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: UI_EnableBookmarkControls ** ** PURPOSE: Enable/Disable buttons appropriately in the Bookmark ** ** dialog. ** ** COMMENTS: ** ****************************************************************************/ void UI_EnableBookmarkControls(HWND hDlg) { if (SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0) == 0 || SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, 0) == LB_ERR) EnableWindow(GetDlgItem(hDlg, IDC_DELETE), FALSE); else EnableWindow(GetDlgItem(hDlg, IDC_DELETE), TRUE); } /**************************************************************************** ** FUNCTION: MagnifyDlgProc ** ** PURPOSE: Set the magnification factor on text. ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI MagnifyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { int mag; char buff[100]; UINT cmd; UINT i; switch (message) { case WM_INITDIALOG: /* display the current magnifier */ mag = View_GetMagnifier(&View); wsprintf(buff, "%d", mag); SendDlgItemMessage(hDlg, IDC_MAGNIFY, WM_SETTEXT, 0, (LPARAM)(LPSTR)buff); SetFocus(GetDlgItem(hDlg, IDC_MAGNIFY)); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDOK: buff[0] = 0; SendDlgItemMessage(hDlg, IDC_MAGNIFY, WM_GETTEXT, sizeof(buff), (LPARAM)(LPSTR)buff); /* check for valid input */ for (i = 0; i < strlen(buff); ++i) if (!isdigit(buff[i])) break; if (i == 0 || i != strlen(buff)) { ErrorMsg("Magnify must use a positive integer.", "error"); SetFocus(GetDlgItem(hDlg, IDC_MAGNIFY)); } else { mag = atoi(buff); View_SetMagnifier(&View, mag); EndDialog(hDlg, TRUE); } return(TRUE); case IDCANCEL: EndDialog(hDlg, FALSE); return(TRUE); } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: IndexDlgProc ** ** PURPOSE: ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI IndexDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { char buff[512]; UINT cmd; int selNumber; switch (message) { case WM_INITDIALOG: MV_KeywordGroups(&View, GetDlgItem(hDlg, IDC_KEYINDEX)); MV_Keywords(&View, GetDlgItem(hDlg, IDC_LIST1), GetDlgItem(hDlg, IDC_KEYINDEX)); EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); SetFocus(GetDlgItem(hDlg, IDC_INDEX)); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_INDEX: if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { if (SendDlgItemMessage(hDlg, IDC_INDEX, WM_GETTEXT, (WPARAM)(sizeof(buff)), (long)(LPSTR)buff) != 0) { /* look up the partial word and complete it */ MV_IndexSelect(&View, GetDlgItem(hDlg, IDC_LIST1), buff); EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); } } break; case IDC_LIST1: /* enable OK button if there is a selection */ if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); /* set the edit control to the selected text */ selNumber = (int)SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, 0); if (selNumber == -1) break; SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, selNumber, (LPARAM)buff); SendDlgItemMessage(hDlg, IDC_INDEX, WM_SETTEXT, 0, (LPARAM)buff); /* if it is not a double click, we are done */ if (GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK) break; /* otherwise fall through */ case IDOK: MV_IndexLookup(hMainWnd, GetDlgItem(hDlg, IDC_LIST1), &View); EndDialog(hDlg, TRUE); return(TRUE); case IDCANCEL: EndDialog(hDlg, FALSE); return(TRUE); case IDC_KEYINDEX: /* load the list box with the keywords for this index group */ if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { MV_Keywords(&View, GetDlgItem(hDlg, IDC_LIST1), GetDlgItem(hDlg, IDC_KEYINDEX)); /* clear the edit control and disable the OK button until there is a keyword selection */ EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); SendDlgItemMessage(hDlg, IDC_INDEX, WM_SETTEXT, (WPARAM)(sizeof(buff)), (long)(LPSTR)""); } break; } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: HistoryDlgProc ** ** PURPOSE: ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI HistoryDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UINT cmd; switch (message) { case WM_INITDIALOG: MV_ShowHistory(&View, GetDlgItem(hDlg, IDC_LIST1)); SetFocus(hDlg); break; case WM_CLOSE: EndDialog(hDlg, FALSE); View.lpApp->hHist = 0; return(TRUE); case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_LIST1: if (GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK) break; /* otherwise fall through */ case IDOK: MV_GoToFromHistory(&View, GetDlgItem(hDlg, IDC_LIST1)); return(TRUE); case IDCANCEL: EndDialog(hDlg, TRUE); View.lpApp->hHist = 0; return(TRUE); } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: MarkDlgProc ** ** PURPOSE: ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI MarkDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static int markType; LPGROUPUI lpGroup; UINT cmd; switch (message) { case WM_INITDIALOG: /* display all currently marked topics/groups */ MV_ShowMarkList(GetDlgItem(hDlg, IDC_MARKLIST)); lpGroup = View.lpGroups; /* walk through the groups and add them to the Groups list box */ while (lpGroup && lpGroup->title) { SendDlgItemMessage(hDlg, IDC_GROUPLIST, LB_ADDSTRING, 0, (LPARAM)(LPSTR)lpGroup->title); ++lpGroup; } /* initialize the dialog to select the current topic for marking */ SendDlgItemMessage( hDlg, IDC_TOPIC, BM_SETCHECK, 1, 0); SendMessage(hDlg, WM_COMMAND, IDC_TOPIC, 0); /* which buttons should be enabled? */ UI_EnableMarkControls(hDlg); break; case WM_CLOSE: EndDialog(hDlg, FALSE); return(TRUE); case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_GROUPS: markType = wParam; UI_EnableMarkControls(hDlg); break; case IDC_TOPIC: markType = wParam; EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), FALSE); UI_EnableMarkControls(hDlg); break; case IDOK: EndDialog(hDlg, TRUE); return(TRUE); case IDC_ADD: MV_AddPrintMark(&View, GetDlgItem(hDlg, IDC_MARKLIST), GetDlgItem(hDlg, IDC_GROUPLIST), markType); /* now there is something in the Mark list */ UI_EnableMarkControls(hDlg); break; case IDC_DELETE: MV_DelPrintMark(GetDlgItem(hDlg, IDC_MARKLIST)); MV_ShowMarkList(GetDlgItem(hDlg, IDC_MARKLIST)); /* which buttons should be enabled? */ UI_EnableMarkControls(hDlg); break; case IDC_CLEAR: MV_FreePrintMarks(); MV_ShowMarkList(GetDlgItem(hDlg, IDC_MARKLIST)); /* There is nothing marked; disable the Delete and Clear buttons */ UI_EnableMarkControls(hDlg); break; case IDC_MARKLIST: case IDC_GROUPLIST: /* list box selection: which buttons should be enabled? */ if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) UI_EnableMarkControls(hDlg); break; } break; } return (FALSE); } /**************************************************************************** ** FUNCTION: UI_EnableMarkControls ** ** PURPOSE: Enables/Disables the MarkDlg buttons appropriately ** ** COMMENTS: ** ****************************************************************************/ void UI_EnableMarkControls(HWND hDlg) { /* if there is nothing marked, disable the Delete and Clear buttons */ if (SendDlgItemMessage(hDlg, IDC_MARKLIST, LB_GETCOUNT, 0, 0) == 0) UI_EnableControls(hDlg, FALSE, IDC_DELETE, IDC_CLEAR, 0); /* if there is nothing selected disable the DELETE */ else if (SendDlgItemMessage(hDlg, IDC_MARKLIST, LB_GETCURSEL, 0, 0) == LB_ERR) { EnableWindow(GetDlgItem(hDlg, IDC_DELETE), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_CLEAR), TRUE); } /* otherwise enable them both */ else UI_EnableControls(hDlg, TRUE, IDC_DELETE, IDC_CLEAR, 0); /* now, if "Current Topic" radio button is selected, enable Add */ if (SendDlgItemMessage( hDlg, IDC_TOPIC, BM_GETCHECK, 0, 0)) { EnableWindow(GetDlgItem(hDlg, IDC_ADD), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), FALSE); } /* otherwise (All Topics in Group), don't enable add unless a Group is selected */ else if (SendDlgItemMessage(hDlg, IDC_GROUPLIST, LB_GETCURSEL, 0, 0) != LB_ERR) { EnableWindow(GetDlgItem(hDlg, IDC_ADD), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), TRUE); } else { EnableWindow(GetDlgItem(hDlg, IDC_ADD), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLIST), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_GROUPLABEL), TRUE); } SetFocus(hDlg); } /**************************************************************************** ** FUNCTION: SourceDlgProc ** ** PURPOSE: Handle the USA SOURCES display window. ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI SourceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UINT cmd; RECT rect; switch (message) { case WM_SIZE: /* size the View display frame */ #define FRAME 20 GetClientRect(hDlg, &rect); MoveWindow(GetDlgItem(hDlg, IDC_STATIC), FRAME, FRAME, rect.right - 2*FRAME, rect.bottom - 2*FRAME, TRUE); /* size the View with a 2 pixel border inside the faceplate window */ UI_SizeViewInWindow(hDlg, IDC_STATIC, SourceView.hView, 2); break; case WM_SYSCOMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); if (cmd != SC_CLOSE) break; /* else fall through */ case WM_CLOSE: View_Close(&SourceView); hSourceWnd = 0; SendMessage(hMainWnd, WM_COMMAND, ID_VIEW_SOURCE, 0); DestroyWindow(hDlg); return(TRUE); } return (FALSE); } /**************************************************************************** ** FUNCTION: SearchResultsDlgProc ** ** PURPOSE: ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI SearchResultsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static RECT oldRect; static int oldPos = FALSE; UINT cmd; switch (message) { case WM_INITDIALOG: /* if there is a saved position, use it */ if (oldPos) MoveWindow(hDlg, oldRect.left, oldRect.top, oldRect.right - oldRect.left, oldRect.bottom - oldRect.top, TRUE); /* put up the search results list (contained in the View) */ View.lpApp->hSearch = hDlg; MV_ShowSearchResults(&View); SetFocus(hDlg); break; case WM_CLOSE: Close: CheckMenuItem(GetMenu(hMainWnd), ID_VIEW_SEARCHRESULTS, FALSE); GetWindowRect(hDlg, &oldRect); oldPos = TRUE; View.lpApp->hSearch = 0; EndDialog(hDlg, TRUE); break; case WM_COMMAND: cmd = GET_WM_COMMAND_ID(wParam, lParam); switch (cmd) { case IDC_LIST1: if (GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK) break; /* otherwise fall through */ case IDC_GOTO: MV_GoToFromSearchResults(GetDlgItem(hDlg, IDC_LIST1), &View); return(TRUE); case IDCANCEL: goto Close; } break; } return (FALSE); } #ifdef COMMENTED_OUT /**************************************************************************** ** FUNCTION: ShowBitmap ** ** PURPOSE: load a bitmap and display it in the window ** ** COMMENTS: ** ****************************************************************************/ void ShowBitmap(char * bitmapName, LPPAINTSTRUCT lps, int xPos, int yPos, int width, int height) { HBITMAP hBitmap, hOldBmap; HDC hNewDC; /* now load the bitmap onto that */ hBitmap = LoadBitmap( hInst, (LPSTR)bitmapName ); if( 0 != hBitmap ) { hNewDC = CreateCompatibleDC( lps->hdc ); hOldBmap = SelectObject( hNewDC, hBitmap ); BitBlt( lps->hdc, xPos, yPos, width, height, hNewDC, 0, 0, SRCCOPY ); SelectObject( hNewDC, hOldBmap ); DeleteObject( hBitmap ); DeleteDC( hNewDC ); } } #endif /**************************************************************************** ** FUNCTION: ErrorMsg ** ** PURPOSE: show an error string dialog box ** ** COMMENTS: ** ****************************************************************************/ void ErrorMsg(LPSTR szText, LPSTR szCaption) { extern HWND hMainWnd; extern HWND hCaptureWnd; MessageBox ( hMainWnd, szText, szCaption, MB_ICONASTERISK | MB_OK); /* MessageBox takes back the mouse. Reset the mouse capture. */ if (hCaptureWnd) SetCapture(hCaptureWnd); } /**************************************************************************** ** FUNCTION: UI_EnableControls ** ** PURPOSE: Enable/Disable a set of controls ** ** COMMENTS: ** ****************************************************************************/ void UI_EnableControls(HWND hDlg, int status, ...) { va_list marker; int control; va_start(marker, status); while ((control = va_arg(marker, int)) != 0) EnableWindow(GetDlgItem(hDlg, control), status); va_end(marker); } /**************************************************************************** ** FUNCTION: UI_EnableMenuItems ** ** PURPOSE: Enable/Disable a set of menu items ** ** COMMENTS: ** ****************************************************************************/ void UI_EnableMenuItems(HWND hWnd, int * pItemList, int iCount, UINT uEnable) { HMENU hMenu = GetMenu(hWnd); while (iCount--) EnableMenuItem(hMenu, *pItemList++, uEnable); } /**************************************************************************** ** FUNCTION: UI_ToggleMenuItem ** ** PURPOSE: toggle the CHECKED/UNCHECKED state of the menu item ** ** COMMENTS: ** ****************************************************************************/ int UI_ToggleMenuItem(HWND hWnd, int iMenuItem) { int state; state = GetMenuState(GetMenu(hWnd), iMenuItem, MF_BYCOMMAND); state = (state == MF_CHECKED ? MF_UNCHECKED : MF_CHECKED); CheckMenuItem(GetMenu(hWnd), iMenuItem, state); return(state); } /**************************************************************************** ** FUNCTION: UI_GetGroups ** ** PURPOSE: Create a group list from the list box selections ** ** COMMENTS: ** ** The returned group list must be freed by the caller. ** ****************************************************************************/ char ** UI_GetGroups(HWND hDlg, LPVIEW lpV) { int i, j, num; char buff[512]; char **lpList; int *lpSels; LPGROUPUI lpGroup; /* get the group list for the title */ lpGroup = lpV->lpGroups; /* get the selection list */ num = (int)SendDlgItemMessage( hDlg, IDC_GROUPLIST, LB_GETSELCOUNT, 0, 0); lpSels = (int *)GlobalAllocPtr(GHND, num * sizeof(int)); SendDlgItemMessage( hDlg, IDC_GROUPLIST, LB_GETSELITEMS, num, (LPARAM)lpSels); lpList = (char **)GlobalAllocPtr(GHND, (num+1) * sizeof(char *)); /* for each one, look up the corresponding groupname */ for (i = 0; i < num; ++i) { /* get the ith selected group title */ SendDlgItemMessage(hDlg, IDC_GROUPLIST, LB_GETTEXT, lpSels[i], (LPARAM)buff); /* look up the associated group name */ for (j = 0; lpGroup[j].title != 0; ++j) { if (_fstrcmp(lpGroup[j].title, buff) == 0) break; } lpList[i] = lpGroup[j].name; } GlobalFreePtr(lpSels); /* terminate the list */ lpList[num] = 0; return(lpList); } /**************************************************************************** ** FUNCTION: UI_UpdateEnable ** ** PURPOSE: Enable/disable things in the UI according to the status ** ** COMMENTS: ** ****************************************************************************/ void UI_UpdateEnable(int statusP, int statusN) { extern int iH; /* history index */ extern int iB; /* history Back index */ HMENU hMenu = GetMenu(hMainWnd); /* "Prev" button and menu item */ EnableWindow(GetDlgItem(hFP, IDC_PREV), statusP); EnableMenuItem(hMenu, ID_TOPIC_PREV, statusP ? MF_ENABLED|MF_BYCOMMAND : MF_GRAYED|MF_BYCOMMAND); /* "Next" button and menu item */ EnableWindow(GetDlgItem(hFP, IDC_NEXT), statusN); EnableMenuItem(hMenu, ID_TOPIC_NEXT, statusN ? MF_ENABLED|MF_BYCOMMAND : MF_GRAYED|MF_BYCOMMAND); /* "History" button and menu entry*/ EnableWindow(GetDlgItem(hFP, IDC_HISTORY), iH != -1); EnableMenuItem(hMenu, ID_TOPIC_HISTORY, iH == -1 ? MF_GRAYED| MF_BYCOMMAND : MF_ENABLED| MF_BYCOMMAND); /* "Back" button and menu entry*/ EnableWindow(GetDlgItem(hFP, IDC_BACK), iB != -1); EnableMenuItem(hMenu, ID_TOPIC_BACK, iB == -1 ? MF_GRAYED| MF_BYCOMMAND : MF_ENABLED| MF_BYCOMMAND); } /**************************************************************************** ** FUNCTION: UI_InitCursors ** ** PURPOSE: Load up the cursors ** ** COMMENTS: ** ****************************************************************************/ void UI_InitCursors(HINSTANCE hInst) { curT = LoadCursor(hInst, "HAND_T"); curE = LoadCursor(hInst, "HAND_E"); curB = LoadCursor(hInst, "HAND_B"); curU = LoadCursor(hInst, "HAND_U"); curArrow = LoadCursor(0, IDC_ARROW); curIbeam = LoadCursor(0, IDC_IBEAM); } /**************************************************************************** ** FUNCTION: UI_DeleteCursors ** ** PURPOSE: Free up the cursors ** ** COMMENTS: ** ****************************************************************************/ void UI_DeleteCursors() { DestroyCursor(curT); DestroyCursor(curE); DestroyCursor(curB); DestroyCursor(curU); DestroyCursor(curArrow); DestroyCursor(curIbeam); } /**************************************************************************** ** FUNCTION: UI_ParseCommandLine ** ** PURPOSE: Put the command line in the same form as a C program. ** ** COMMENTS: ** ****************************************************************************/ int UI_ParseCmdLine(LPSTR lpC, LPSTR *argv, int maxArg) { int i; for (i = 0; i < maxArg; ++i) { if (*lpC == 0) break; while (*lpC && isspace(*lpC)) ++lpC; argv[i] = lpC; while (*lpC && !isspace(*lpC)) ++lpC; if (*lpC != 0) *lpC++ = 0; } return(i); } /**************************************************************************** ** FUNCTION: UI_OpenFile ** ** PURPOSE: Open a title and create the Views into it. Also, update ** ** the UI appropriately. ** ** COMMENTS: ** ****************************************************************************/ int UI_OpenFile(LPSTR lpFileName) { int menuItem, menuStatus, state; LPSTR lp; char buff[_MAX_PATH]; /* close any title that is already open */ View_Close(&View); View_Close(&SourceView); /* create the MediaView */ if (View_Open(lpFileName, &View) != 0) { ErrorMsg("Cannot open View", "Error"); return(ERR_FAILED); } /* set the title bar to the title */ TitleGetInfo(View.hTitle, TTLINF_TITLE, 0, (long)(LPSTR)buff); SetWindowText(hMainWnd, buff); /* enable the button bar */ UI_EnableControls(hFP, TRUE, IDC_CONTENTS, IDC_INDEX, IDC_SEARCH, 0); /* enable the portions of the menu that need an open file */ UI_EnableMenuItems(hMainWnd, MenuItems, DIMENSION(MenuItems), MF_ENABLED|MF_BYCOMMAND); /* and disable the prev/next */ UI_UpdateEnable(FALSE, FALSE); /* The source window is for demonstration with the * USA title only. The code in this next block should * be deleted in a general purpose browser application. * It demonstrates how a second M12 file can be opened and * a simultaneous View kept into that title. * * Create the View Source display window. Grey out the * menu if the file doesn't exist. */ lp = _fstrrchr(lpFileName, '\\'); if (lp++ == 0) lp = lpFileName; if (_fstricmp(lp, szUSATitle) == 0) { if (lp != lpFileName) { /* get a SOURCES file in the same directory as the USA app */ _fstrncpy(buff, lpFileName, lp - lpFileName); buff[lp - lpFileName] = 0; _fstrcat(buff, szSourceTitle); lp = buff; } else lp = szSourceTitle; /* the app title is USA.M12 ... try to open SOURCES.M12 */ if (View_Open(lp, &SourceView) != 0) { ErrorMsg("Cannot open SOURCES title", "Error"); menuStatus = MF_GRAYED|MF_BYCOMMAND; } else { menuStatus = MF_ENABLED|MF_BYCOMMAND; MV_SourceUpdate(View_ValidMV(&View)); } } else { /* if not USA.M12, disable the source window */ menuStatus = MF_GRAYED|MF_BYCOMMAND; } /* if disabled, make sure it is not visible */ state = GetMenuState(GetMenu(View.lpApp->hMain), ID_VIEW_SOURCE, MF_BYCOMMAND); if ((menuStatus & MF_GRAYED) && (state & MF_CHECKED)) SendMessage(View.lpApp->hMain, WM_COMMAND, ID_VIEW_SOURCE, 0); /* and disable/enable appropriately */ menuItem = ID_VIEW_SOURCE; UI_EnableMenuItems(hMainWnd, &menuItem, 1, menuStatus); return(0); }