WINDIFF.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:93k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /****************************** Module Header *******************************
- * Module Name: WINDIFF.C
- *
- * File and directory comparisions.
- *
- * Functions:
- *
- * windiff_UI()
- * WinMain()
- * windiff_usage()
- * Poll()
- * DoResize()
- * AboutBox()
- * DoPrint()
- * FindNextChange()
- * FindPrevChange()
- * WriteProfileInt()
- * ToOutline()
- * ToMoved()
- * do_editfile()
- * do_editthread()
- * SetStatus()
- * SetNames()
- * IsBusy()
- * BusyError()
- * StateToColour()
- * SetSelection()
- * do_gethdr()
- * do_getprops()
- * do_getdata()
- * SvrClose()
- * TableServer()
- * wd_dirdialog()
- * wd_copy()
- * InitApplication()
- * InitInstance()
- * CreateTools()
- * DeleteTools()
- * MainWndProc()
- * SetBusy()
- * SetNotBusy()
- * SetSelection()
- * SetButtonText()
- * ToExpand()
- * ParseArgs()
- * wd_initial()
- *
- * Comments:
- *
- * Compare two directories (including all files and subdirs). Look for names
- * that are present in both (report all that are not). For files that
- * are present in both, produce a line-by-line comparison of the differences
- * between the two files (if any).
- *
- * Overview of Windiff internals - the whole program.
- *
- * Windiff is built from several modules (a "module" has a .h file
- * which describes its interface and a .c file which implements it).
- * Apart from THIS comment which tries to give an overview of the whole
- * scheme of things, each module is as self-contained as possible.
- * This is enforced by the use of opaque data types. Modules cannot
- * see each others' internal data structures. Modules are abstract
- * data types. The term "Module" (from Modula2) and "Class" (from C++)
- * are used synonymously.
- *
- * Windiff - main program - parse arguments, put up main window,
- * handle input, calling other modules as needed
- * invoke table class to create the main display and
- * service callbacks from the table class.
- * Contains global flags for options (e.g. ignore_blanks)
- * list - (in gutils) a generalised LIST of anything data type
- * has full set of operations for insert, delete, join etc.
- * line - a LINE is a numbered line of text. Information is kept to
- * allow fast comparisons of LINEs. A LINE can hold a
- * link to another LINE. The links are used to connect
- * lines in one file to matching lines in the other file.
- * file - a FILEDATA represents a file as a file name in the form
- * of a DIRITEM and a LIST of LINEs
- * scandir - a DIRITEM represents information about a file. (for
- * instance its name, whether it has a local copy).
- * compitem - a COMPITEM is a pair of files together with information
- * on how they compare in the form of a breakdown of the
- * files into a LIST of matching or non-matching sections.
- * Either file can be absent. This module contains the
- * file "contrast" algorithm used for the actual comparison
- * tree (in gutils) A binary tree. Important because it is what
- * gives the file comparison its speed as it makes it
- * an "N log N" algorithm rather than "N squared"
- * complist - a COMPLIST is the master data structure. It has a DIRLIST
- * of the left hand files, a DIRLIST of the right hand files
- * and a LIST of COMPITEMs. The left and right hand DIRLISTs
- * are working data used to produce the COMPLIST. The LIST
- * is displayed as the outline table. Any given COMPITEM can
- * be displayed as an expanded item.
- * section - a SECTION is a section of a file (first line, last line)
- * and information as to what it matches in the other file.
- * bar.c - the picture down the left of the screen
- * has a WNDPROC.
- * view - Although the COMPLIST is the master state, it doesn't do
- * all the work itself. The data is actually displayed by
- * the table class which is highly generalised. View
- * owns a COMPLIST (and therefore calls upon the functions
- * in complist to fill it and interrogate it) and calls
- * upon (and is called back by) the functions in table to
- * actually display it. Read about table in gutils.h
- * table.c (in gutils) a highly generalised system for displaying
- * data in rows and columns. The interface is in gutils.h.
- * status.c (in gutils) the status line at the top. See gutils.h
- *************************************************************************
- *
- * Overview of this file:
- *
- * We create a table window (gutils.dll) to show the files and the
- * results of their comparisons. We create a COMPLIST object representing
- * a list of files and their differences, and a VIEW object to map between
- * the rows of the table window and the COMPLIST.
- *
- * This module is responsible for creating and managing the main window,
- * placing the child windows (table, status window etc) within it, and
- * handling all menu items. We maintain global option flags set by
- * menu commands.
- *
- * Creating a COMPLIST creates a list of unmatched files, and of matching
- * files that are compared with each other (these are COMPITEMS).
- * The VIEW provides a mapping between rows on the screen, and items in
- * the COMPLIST.
- *
- * This version tries to maintain a responsive user interface by
- * creating worker threads to do long jobs. This potentially creates
- * conflicts between the threads as they will both want to update common
- * variables (for instance the UI thread may be changing the options to
- * exclude identical files while the worker thread is adding in the
- * results of new comparisons). Critical sections are used to manage
- * the conflicts.
- *
- * The Edit options invoke an editor on a separate thread. This allows
- * us to repaint our window and thereby allow the user to refer back to
- * what he saw before invoking the editor. When he's finished editing,
- * we would of course like to refresh things and if this is still on the
- * separate thread it might clash. We avoid this clash by POSTing ourselves
- * a (WM_COMMAND, IDM_UPDATE) message.
- *
- ****************************************************************************/
- #include <windows.h>
- #include <shellapi.h>
- #include <stdlib.h>
- #include <commdlg.h>
- #include <string.h>
- #include "gutils.h"
- #include "table.h"
- #include "list.h"
- #include "scandir.h" /* needed for file.h */
- #include "file.h" /* needed for compitem.h */
- #include "compitem.h" /* needed for view.h */
- #include "complist.h"
- #include "view.h"
- #include "state.h"
- #include "windiff.h"
- #include "wdiffrc.h"
- /*--constants and data types--------------------------------------------*/
- int Version = 2;
- int SubVersion = 01;
- /* When we print the current table, we pass this id as the table id
- * When we are queried for the properties of this table, we know they
- * want the printing properties for the current view. We use this to
- * select different fonts and colours for the printer.
- */
- #define TABID_PRINTER 1
- /*
- * structure containing args passed to worker thread in initial
- * case (executing command line instructions).
- */
- typedef struct {
- LPSTR first;
- LPSTR second;
- LPSTR savelist;
- UINT saveopts;
- VIEW view;
- BOOL fDeep;
- } THREADARGS, FAR * PTHREADARGS;
- /* Structure containing all the arguments we'd like to give to do_editfile
- Need a structure because CreateThread only allows for one argument.
- */
- typedef struct {
- VIEW view;
- int option;
- int selection;
- } EDITARGS, FAR * PEDITARGS;
- /*---- colour scheme------------------------------- */
- /* outline */
- DWORD rgb_outlinehi = RGB(255, 0, 0); /* hilighted files in outline mode */
- /* expand view */
- DWORD rgb_leftfore = RGB( 0, 0, 0); /* foregrnd for left lines */
- DWORD rgb_leftback = RGB(255, 0, 0); /* backgrnd for left lines */
- DWORD rgb_rightfore = RGB( 0, 0, 0); /* foregrnd for right lines*/
- DWORD rgb_rightback = RGB(255, 255, 0); /* backgrnd for right lines*/
- /* moved lines */
- DWORD rgb_mleftfore = RGB( 0, 0, 128); /* foregrnd for moved-left */
- DWORD rgb_mleftback = RGB(255, 0, 0); /* backgrnd for moved-left */
- DWORD rgb_mrightfore = RGB( 0, 0, 255); /* foregrnd for moved-right*/
- DWORD rgb_mrightback = RGB(255, 255, 0); /* backgrnd for moved-right*/
- /* bar window */
- DWORD rgb_barleft = RGB(255, 0, 0); /* bar sections in left only */
- DWORD rgb_barright = RGB(255, 255, 0); /* bar sections in right only */
- DWORD rgb_barcurrent = RGB( 0, 0, 255); /* current pos markers in bar */
- /* module static data -------------------------------------------------*/
- /* current value of window title */
- char AppTitle[256];
- HWND hwndClient; /* main window */
- HWND hwndRCD; /* table window */
- HWND hwndStatus; /* status bar across top */
- HWND hwndBar; /* graphic of sections as vertical bars */
- HACCEL haccel;
- /* The status bar told us it should be this high. Rest of client area
- * goes to the hwndBar and hwndRCD.
- */
- int status_height;
- HINSTANCE hInst; /* handle to current app instance */
- HMENU hMenu; /* handle to menu for hwndClient */
- int nMinMax = SW_SHOWNORMAL; /* default state of window normal */
- /* The message sent to us as a callback by the table window needs to be
- * registered - table_msgcode is the result of the RegisterMessage call
- */
- UINT table_msgcode;
- /* True if we are currently doing some scan or comparison.
- * Must get critical section before checking/changing this (call
- * SetBusy.
- */
- BOOL fBusy = FALSE;
- int selection = -1; /* selected row in table*/
- /* Options for DisplayMode field indicating what is currently shown.
- * We use this to know whether or not to show the graphic bar window.
- */
- #define MODE_NULL 0 /* nothing displayed */
- #define MODE_OUTLINE 1 /* a list of files displayed */
- #define MODE_EXPAND 2 /* view is expanded view of one file */
- int DisplayMode = MODE_NULL; /* indicates whether we are in expand mode */
- VIEW current_view = NULL;
- /* command line parameters */
- extern int __argc;
- extern char ** __argv;
- BOOL bAbort = FALSE; /* set to request abort of current operation */
- char editor_cmdline[256] = "notepad %p"; /* editor cmdline */
- /* slick version is "s %p -#%l" */
- /* app-wide global data --------------------------------------------- */
- /* Handle returned from gmem_init - we use this for all memory allocations */
- HANDLE hHeap;
- /* Current state of menu options */
- int line_numbers = IDM_LNRS;
- int expand_mode = IDM_BOTHFILES;
- int outline_include = INCLUDE_LEFTONLY|INCLUDE_RIGHTONLY|INCLUDE_SAME|INCLUDE_DIFFER;
- BOOL ignore_blanks = TRUE;
- BOOL picture_mode = TRUE;
- /* function prototypes ---------------------------------------------*/
- BOOL InitApplication(HINSTANCE hInstance);
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
- void CreateTools(void);
- void DeleteTools(void);
- long APIENTRY MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam);
- BOOL SetBusy(void);
- void SetNotBusy(void);
- void SetSelection(long rownr);
- void SetButtonText(LPSTR cmd);
- BOOL ToExpand(HWND hwnd);
- void ParseArgs(int argc, char ** argv);
- DWORD wd_initial(LPVOID arg);
- static HANDLE ghThread = NULL;
- static DWORD gdwMainThreadId; /* threadid of main (user interface) thread
- initialised in winmain(), thereafter constant.
- See windiff_UI()
- */
- /***************************************************************************
- * Function: windiff_UI
- *
- * Purpose:
- *
- * If you are about to put up a dialog box or in fact process input in any way
- * on any thread other than the main thread - or if you MIGHT be on a thread other
- * than the main thread, then you must call this function with TRUE before doing
- * it and with FALSE immediately afterwards. Otherwise you will get one of a
- * number of flavours of not-very-responsiveness
- */
- void windiff_UI(BOOL bAttach)
- {
- DWORD dwThreadId = GetCurrentThreadId();
- if (dwThreadId==gdwMainThreadId) return;
- if (bAttach) GetDesktopWindow();
- AttachThreadInput(dwThreadId, gdwMainThreadId, bAttach);
- } /* windiff_UI */
- /***************************************************************************
- * Function: WinMain
- *
- * Purpose:
- *
- * Main entry point. Register window classes, create windows,
- * parse command line arguments and then perform a message loop
- */
- int WINAPI
- WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
- {
- MSG msg;
- gdwMainThreadId = GetCurrentThreadId();
- /* create any pens/brushes etc and read in profile defaults */
- CreateTools();
- /* init window class unless other instances running */
- if (!hPrevInstance)
- if (!InitApplication(hInstance))
- return(FALSE);
- /* init this instance - create all the windows */
- if (!InitInstance(hInstance, nCmdShow))
- return(FALSE);
- ParseArgs(__argc, __argv);
- /* message loop */
- while(GetMessage(&msg, NULL, 0, 0)) {
- if (!TranslateAccelerator(hwndClient, haccel, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- return (msg.wParam);
- }
- /***************************************************************************
- * Function: InitApplication
- *
- * Purpose:
- *
- * Register window class for the main window and the bar window.
- */
- BOOL
- InitApplication(HINSTANCE hInstance)
- {
- WNDCLASS wc;
- BOOL resp;
- /* register the bar window class */
- InitBarClass(hInstance);
- wc.style = 0;
- wc.lpfnWndProc = MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, "WinDiff");
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = NULL;
- wc.lpszClassName = "WinDiffViewerClass";
- wc.lpszMenuName = NULL;
- resp = RegisterClass(&wc);
- return(resp);
- }
- /***************************************************************************
- * Function: InitInstance
- *
- * Purpose:
- *
- * Create and show the windows
- */
- BOOL
- InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
- RECT rect;
- HANDLE hstatus;
- int bar_width;
- RECT childrc;
- hInst = hInstance;
- /* initialise a heap. we use this one heap throughout
- * the app. for all memory requirements
- */
- hHeap = gmem_init();
- /* initialise the list package */
- List_Init();
- hMenu = LoadMenu(hInstance, "WinDiffMenu");
- haccel = LoadAccelerators(hInstance, "WinDiffAccel");
- /* create the main window */
- hwndClient = CreateWindow("WinDiffViewerClass",
- "WinDiff",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- hMenu,
- hInstance,
- NULL
- );
- if (!hwndClient) {
- return(FALSE);
- }
- /* create 3 child windows, one status, one table and one bar
- * Initially, the bar window is hidden and covered by the table.
- */
- /* create a status bar window as
- * a child of the main window.
- */
- /* build a status struct for two labels and an abort button */
- hstatus = StatusAlloc(3);
- StatusAddItem(hstatus, 0, SF_STATIC, SF_LEFT|SF_VAR|SF_SZMIN, IDL_STATLAB, 14, NULL);
- StatusAddItem(hstatus, 1, SF_BUTTON, SF_RIGHT|SF_RAISE, IDM_ABORT, 8,
- LoadRcString(IDS_EXIT));
- StatusAddItem(hstatus, 2, SF_STATIC, SF_LOWER|SF_LEFT|SF_VAR,
- IDL_NAMES, 60, NULL);
- /* ask the status bar how high it should be for the controls
- * we have chosen, and save this value for re-sizing.
- */
- status_height = StatusHeight(hstatus);
- /* create a window of this height */
- GetClientRect(hwndClient, &rect);
- childrc = rect;
- childrc.bottom = status_height;
- hwndStatus = StatusCreate(hInst, hwndClient, IDC_STATUS, &childrc,
- hstatus);
- /* layout constants are stated as percentages of the window width */
- bar_width = (rect.right - rect.left) * BAR_WIN_WIDTH / 100;
- /* create the table class covering all the remaining part of
- * the main window
- */
- hwndRCD = CreateWindow(TableClassName,
- NULL,
- WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL,
- 0,
- status_height,
- (int)(rect.right - rect.left),
- (int)(rect.bottom - status_height),
- hwndClient,
- (HANDLE) IDC_RCDISP1,
- hInst,
- NULL);
- /* create a bar window as a child of the main window.
- * this window remains hidden until we switch into MODE_EXPAND
- */
- hwndBar = CreateWindow("BarClass",
- NULL,
- WS_CHILD | WS_VISIBLE,
- 0,
- status_height,
- bar_width,
- (int)(rect.bottom - status_height),
- hwndClient,
- (HANDLE) IDC_BAR,
- hInst,
- NULL);
- /* nMinMax indicates whether we are to be minimised on startup,
- * on command line parameters
- */
- ShowWindow(hwndBar, SW_HIDE);
- if (GetProfileInt(APPNAME, "OutlineSaved", 0))
- {
- WINDOWPLACEMENT wp;
- /* restore the previous expanded size and position */
- wp.length = sizeof( WINDOWPLACEMENT );
- wp.flags = 0;
- wp.showCmd = GetProfileInt( APPNAME, "OutlineShowCmd",
- SW_SHOWNORMAL);
- wp.ptMaxPosition.x = GetProfileInt( APPNAME, "OutlineMaxX", 0);
- wp.ptMaxPosition.y = GetProfileInt( APPNAME, "OutlineMaxY", 0);
- wp.rcNormalPosition.left = (int)GetProfileInt( APPNAME, "OutlineNormLeft", (UINT)(-1));
- wp.rcNormalPosition.top = (int)GetProfileInt( APPNAME, "OutlineNormTop", (UINT)(-1));
- wp.rcNormalPosition.right = (int)GetProfileInt( APPNAME, "OutlineNormRight", (UINT)(-1));
- wp.rcNormalPosition.bottom = (int)GetProfileInt( APPNAME, "OutlineNormBottom",(UINT)(-1));
- SetWindowPlacement(hwndClient,&wp);
- }
- else ShowWindow(hwndClient, nMinMax);
- UpdateWindow(hwndClient);
- /* initialise busy flag and status line to show we are idle
- * (ie not comparing or scanning)
- */
- SetNotBusy();
- return(TRUE);
- } /* InitInstance */
- /***************************************************************************
- * Function: windiff_usage
- *
- * Purpose:
- *
- * Complain to command line users about poor syntax,
- * will be replaced by proper help file.
- */
- void
- windiff_usage(LPSTR msg)
- {
- int retval;
- TCHAR szBuf[MAX_PATH];
- if (msg==NULL)
- msg = LoadRcString(IDS_USAGE_STR);
- LoadString(hInst, IDS_WINDIFF_USAGE, szBuf, sizeof(szBuf));
- retval = MessageBox(hwndClient,
- msg,
- szBuf, MB_ICONINFORMATION|MB_OKCANCEL);
- if (retval == IDCANCEL) {
- exit(1);
- }
- }
- /***************************************************************************
- * Function: ParseArgs
- *
- * Purpose:
- *
- * Parse command line arguments
- *
- * The user can give one or two paths. If only one, we assume the second
- * is '.' for the current directory. If one of the two paths is a directory
- * and the other a file, we compare a file of the same name in the two dirs.
- *
- * The command -s filename causes the outline list to be written to a file
- * and then the program exits. -s{slrd} filename allows selection of which
- * files are written out; by default, we assume -sld for files left and different.
- *
- * -T means tree. Go deep.
- *
- * The default is Deep, -L overrides and implies shallow, -T overrides -L
- */
- void
- ParseArgs(int argc, char ** argv)
- {
- int i;
- LPSTR chp;
- PTHREADARGS ta;
- DWORD threadid;
- /* thread args can't be on the stack since the stack will change
- * before the thread completes execution
- */
- ta = (PTHREADARGS) gmem_get(hHeap, sizeof(THREADARGS));
- ta->first = NULL;
- ta->second = NULL;
- ta->savelist = NULL;
- ta->saveopts = 0;
- ta->fDeep = FALSE; /* No -T option seen yet */
- for (i = 1; i < argc; i++) {
- /* is this an option ? */
- if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
- switch(argv[i][1]) {
- case 's':
- case 'S':
- /* read letters for the save option: s,l,r,d */
- for(chp = &argv[i][2]; *chp != ' '; chp++) {
- switch(*chp) {
- case 's':
- case 'S':
- ta->saveopts |= INCLUDE_SAME;
- break;
- case 'l':
- case 'L':
- ta->saveopts |= INCLUDE_LEFTONLY;
- break;
- case 'r':
- case 'R':
- ta->saveopts |= INCLUDE_RIGHTONLY;
- break;
- case 'd':
- case 'D':
- ta->saveopts |= INCLUDE_DIFFER;
- break;
- default:
- windiff_usage(NULL);
- return;
- }
- }
- if (ta->saveopts == 0) {
- /* default to left and differ */
- ta->saveopts = (INCLUDE_LEFTONLY) | (INCLUDE_DIFFER);
- }
- ta->savelist = argv[++i];
- break;
- case 't':
- case 'T':
- ta->fDeep = TRUE;
- break;
- default:
- windiff_usage(NULL);
- return;
- }
- } else {
- if (ta->first == NULL) {
- ta->first = argv[i];
- } else {
- ta->second = argv[i];
- }
- }
- }
- /* set the correct depth */
- if (ta->fDeep)
- ; /* explicitly set -- leave it alone */
- else ta->fDeep = TRUE; /* global default */
- /* any paths to scan ? */
- if (ta->first == NULL) {
- return;
- }
- if (ta->second == NULL) {
- ta->second = ".";
- }
- SetBusy();
- /* minimise the window if -s flag given */
- if (ta->savelist != NULL) {
- ShowWindow(hwndClient, SW_MINIMIZE);
- }
- /* make an empty view */
- current_view = view_new(hwndRCD);
- DisplayMode = MODE_OUTLINE;
- ta->view = current_view;
- /* attempt to create a worker thread */
- ghThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wd_initial, (LPVOID) ta,
- 0, &threadid);
- if (ghThread == NULL)
- {
- wd_initial( (LPVOID) ta);
- }
- } /* ParseArgs */
- /***************************************************************************
- * Function: CreateTools
- *
- * Purpose:
- *
- * Create any pens/brushes, and read defaults
- * from the profile file for menu settings etc.
- */
- void
- CreateTools(void)
- {
- /* standard message that table class sends us for
- * notifications and queries.
- */
- table_msgcode = RegisterWindowMessage(TableMessage);
- line_numbers = GetProfileInt(APPNAME, "LineNumbers", line_numbers);
- outline_include = GetProfileInt(APPNAME, "FileInclude", outline_include);
- ignore_blanks = GetProfileInt(APPNAME, "Blanks", ignore_blanks);
- picture_mode = GetProfileInt(APPNAME, "Picture", picture_mode);
- GetProfileString(APPNAME, "Editor", editor_cmdline, (LPTSTR)editor_cmdline,
- sizeof(editor_cmdline));
- InitializeCriticalSection(&CSWindiff);
- }
- /***************************************************************************
- * Function: DeleteTools
- *
- * Purpose:
- *
- * Delete any pens or brushes that were created in CreateTools
- */
- void
- DeleteTools(void)
- {
- DeleteCriticalSection(&CSWindiff);
- }
- /***************************************************************************
- * Function:
- *
- * Purpose:
- *
- * Check whether we have had an abort request (IDM_ABORT), and
- * return TRUE if abort requested, otherwise FALSE
- */
- BOOL
- Poll(void)
- {
- return(bAbort);
- }
- /***************************************************************************
- * Function: DoResize
- *
- * Purpose:
- *
- * Position child windows on a resize of the main window
- */
- void
- DoResize(HWND hWnd)
- {
- RECT rc;
- int bar_width;
- GetClientRect(hWnd, &rc);
- MoveWindow(hwndStatus, 0, 0, rc.right - rc.left, status_height, TRUE);
- bar_width = (rc.right - rc.left) * BAR_WIN_WIDTH / 100;
- /* bar window is hidden unless in expand mode */
- if ((DisplayMode == MODE_EXPAND) && (picture_mode)) {
- ShowWindow(hwndBar, SW_SHOW);
- MoveWindow(hwndBar, 0, status_height,
- bar_width, rc.bottom - status_height, TRUE);
- MoveWindow(hwndRCD, bar_width, status_height,
- (rc.right - rc.left) - bar_width,
- rc.bottom - status_height, TRUE);
- } else {
- MoveWindow(hwndRCD, 0, status_height, (rc.right - rc.left),
- rc.bottom - status_height, TRUE);
- ShowWindow(hwndBar, SW_HIDE);
- }
- }
- /***************************************************************************
- * Function: AboutBox
- *
- * Purpose:
- *
- * Standard processing for About box.
- */
- int APIENTRY
- AboutBox(HWND hDlg, unsigned message, UINT wParam, LONG lParam)
- {
- char ch[256];
- switch (message) {
- case WM_INITDIALOG:
- wsprintf((LPTSTR)ch, "%d.%02d", Version, SubVersion);
- SetDlgItemText(hDlg, IDD_VERSION, ch);
- return(TRUE);
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam)) {
- case IDOK:
- EndDialog(hDlg, 0);
- return(TRUE);
- }
- break;
- }
- return(FALSE);
- }
- /* -- menu commands ---------------------------------------------------*/
- /***************************************************************************
- * Function: DoPrint
- *
- * Purpose:
- *
- * Print the current view
- */
- void
- DoPrint(void)
- {
- Title head, foot;
- PrintContext context;
- TCHAR szPage[50];
- /* print context contains the header and footer. Use the
- * default margins and printer selection
- */
- /* we set the table id to be TABID_PRINTER. When the table calls
- * back to get text and properties, we use this to indicate
- * that the table refered to is the 'current_view', but in print
- * mode, and thus we will use different colours/fonts.
- */
- context.head = &head;
- context.foot = &foot;
- context.margin = NULL;
- context.pd = NULL;
- context.id = TABID_PRINTER;
- /* header is filenames or just WinDiff if no names known*/
- if (strlen(AppTitle) > 0) {
- head.ptext = AppTitle;
- } else {
- head.ptext = "WinDiff";
- }
- /* header is centred, footer is right-aligned and
- * consists of the page number
- */
- head.props.valid = P_ALIGN;
- head.props.alignment = P_CENTRE;
- lstrcpy(szPage,LoadRcString(IDS_PAGE));
- foot.ptext = (LPSTR)szPage;
- foot.props.valid = P_ALIGN;
- foot.props.alignment = P_RIGHT;
- SendMessage(hwndRCD, TM_PRINT, 0, (DWORD) (LPSTR) &context);
- }
- /***************************************************************************
- * Function: FindNextChange
- *
- * Purpose:
- *
- * Find the next line in the current view that is
- * not STATE_SAME. Start from the current selection, if valid, or
- * from the top of the window if no selection.
- *
- */
- BOOL
- FindNextChange(void)
- {
- long row;
- /* start from the selection or top of the window if no selection */
- if (selection >= 0) {
- row = selection;
- } else {
- row = (int) SendMessage(hwndRCD, TM_TOPROW, FALSE, 0);
- }
- /* find the next 'interesting' line */
- row = view_findchange(current_view, row, TRUE);
- if (row >= 0) {
- SetSelection(row);
- return(TRUE);
- } else {
- windiff_UI(TRUE);
- MessageBox(hwndClient, LoadRcString(IDS_NO_MORE_CHANGES), "Windiff",
- MB_ICONINFORMATION|MB_OK);
- windiff_UI(FALSE);
- return(FALSE);
- }
- }
- /***************************************************************************
- * Function: FindPrevChange
- *
- * Purpose:
- *
- * Find the previous line in the current view that is not STATE_SAME
- */
- BOOL
- FindPrevChange(void)
- {
- long row;
- /* start from the selection or top of window if no selection */
- if (selection >= 0) {
- row = selection;
- } else {
- row = (int) SendMessage(hwndRCD, TM_TOPROW, FALSE, 0);
- }
- /* find the previous 'interesting' line */
- row = view_findchange(current_view, row, FALSE);
- if (row >= 0) {
- SetSelection(row);
- return(TRUE);
- } else {
- windiff_UI(TRUE);
- MessageBox(hwndClient, LoadRcString(IDS_NO_PREV_CHANGES), "Windiff",
- MB_ICONINFORMATION|MB_OK);
- windiff_UI(FALSE);
- return(FALSE);
- }
- }
- /***************************************************************************
- * Function: WriteProfileInt
- *
- */
- BOOL WriteProfileInt(LPSTR AppName, LPSTR Key, int Int)
- { char Str[40];
- wsprintf((LPTSTR)Str, "%d", Int);
- return WriteProfileString(AppName, Key, Str);
- } /* WriteProfileInt */
- /***************************************************************************
- * Function: ToExpand
- *
- * Purpose:
- *
- * Switch to expand view of the selected line
- */
- BOOL
- ToExpand(HWND hwnd)
- {
- if (selection < 0) {
- return(FALSE);
- }
- if (!view_isexpanded(current_view)) {
- /* save the current outline size and position */
- WINDOWPLACEMENT wp;
- if (GetWindowPlacement(hwndClient,&wp)) {
- WriteProfileInt(APPNAME, "OutlineShowCmd", wp.showCmd);
- WriteProfileInt(APPNAME, "OutlineMaxX", wp.ptMaxPosition.x);
- WriteProfileInt(APPNAME, "OutlineMaxY", wp.ptMaxPosition.y);
- WriteProfileInt(APPNAME, "OutlineNormLeft", wp.rcNormalPosition.left);
- WriteProfileInt(APPNAME, "OutlineNormTop", wp.rcNormalPosition.top);
- WriteProfileInt(APPNAME, "OutlineNormRight", wp.rcNormalPosition.right);
- WriteProfileInt(APPNAME, "OutlineNormBottom", wp.rcNormalPosition.bottom);
- WriteProfileInt(APPNAME, "OutlineSaved", 1);
- }
- /* restore the previous expanded size and position, if any */
- if (GetProfileInt(APPNAME, "ExpandedSaved", 0)) {
- wp.flags = 0;
- wp.showCmd
- = GetProfileInt( APPNAME, "ExpandShowCmd"
- , SW_SHOWMAXIMIZED);
- wp.ptMaxPosition.x
- = GetProfileInt( APPNAME, "ExpandMaxX", 0);
- wp.ptMaxPosition.y
- = GetProfileInt( APPNAME, "ExpandMaxY", 0);
- wp.rcNormalPosition.left
- = GetProfileInt( APPNAME, "ExpandNormLeft"
- , wp.rcNormalPosition.left);
- wp.rcNormalPosition.top
- = GetProfileInt( APPNAME, "ExpandNormTop"
- , wp.rcNormalPosition.top);
- wp.rcNormalPosition.right
- = GetProfileInt( APPNAME, "ExpandNormRight"
- , wp.rcNormalPosition.right);
- wp.rcNormalPosition.bottom
- = GetProfileInt( APPNAME, "ExpandNormBottom"
- , wp.rcNormalPosition.bottom);
- SetWindowPlacement(hwndClient,&wp);
- }
- else ShowWindow(hwndClient, SW_SHOWMAXIMIZED);
- }
- /*change the view mapping to expand mode */
- if (view_expand(current_view, selection)) {
- /* ok - we now have an expanded view - change status
- * to show this
- */
- DisplayMode = MODE_EXPAND;
- /* resize to show the graphic bar picture */
- DoResize(hwndClient);
- /* change button,status text-if we are not still busy*/
- if (!fBusy) {
- TCHAR szBuf[10];
- lstrcpy(szBuf,LoadRcString(IDS_OUTLINE));
- /* the status field when we are expanded shows the
- * tag field (normally the file name) for the
- * item we are expanding
- */
- SetStatus(view_getcurrenttag(current_view) );
- SetButtonText(szBuf);
- }
- return(TRUE);
- }
- return(FALSE);
- } /* ToExpand */
- /***************************************************************************
- * Function: ToOutline
- *
- * Purpose:
- *
- * Switch back to outline view - showing just the list of file names.
- */
- void
- ToOutline(HWND hwnd)
- {
- if (view_isexpanded(current_view)) {
- /* save the current expanded size and position */
- WINDOWPLACEMENT wp;
- if (GetWindowPlacement(hwndClient,&wp)) {
- WriteProfileInt(APPNAME, "ExpandShowCmd", wp.showCmd);
- WriteProfileInt(APPNAME, "ExpandMaxX", wp.ptMaxPosition.x);
- WriteProfileInt(APPNAME, "ExpandMaxY", wp.ptMaxPosition.y);
- WriteProfileInt(APPNAME, "ExpandNormLeft", wp.rcNormalPosition.left);
- WriteProfileInt(APPNAME, "ExpandNormTop", wp.rcNormalPosition.top);
- WriteProfileInt(APPNAME, "ExpandNormRight", wp.rcNormalPosition.right);
- WriteProfileInt(APPNAME, "ExpandNormBottom", wp.rcNormalPosition.bottom);
- WriteProfileInt(APPNAME, "ExpandedSaved", 1);
- }
- /* restore the previous expanded size and position, if any */
- if (GetProfileInt(APPNAME, "OutlineSaved", 0)) {
- wp.flags = 0;
- wp.showCmd
- = GetProfileInt( APPNAME, "OutlineShowCmd"
- , SW_SHOWNORMAL);
- wp.ptMaxPosition.x
- = GetProfileInt( APPNAME, "OutlineMaxX", 0);
- wp.ptMaxPosition.y
- = GetProfileInt( APPNAME, "OutlineMaxY", 0);
- wp.rcNormalPosition.left
- = GetProfileInt( APPNAME, "OutlineNormLeft"
- , wp.rcNormalPosition.left);
- wp.rcNormalPosition.top
- = GetProfileInt( APPNAME, "OutlineNormTop"
- , wp.rcNormalPosition.top);
- wp.rcNormalPosition.right
- = GetProfileInt( APPNAME, "OutlineNormRight"
- , wp.rcNormalPosition.right);
- wp.rcNormalPosition.bottom
- = GetProfileInt( APPNAME, "OutlineNormBottom"
- , wp.rcNormalPosition.bottom);
- SetWindowPlacement(hwndClient,&wp);
- }
- ShowWindow(hwndClient, SW_SHOWNORMAL);
- }
- DisplayMode = MODE_OUTLINE;
- /* switch mapping back to outline view */
- view_outline(current_view);
- /* hide bar window and resize to cover */
- DoResize(hwndClient);
- /* change label on button */
- if (!fBusy) {
- TCHAR szBuf[8];
- lstrcpy(szBuf,LoadRcString(IDS_EXPAND));
- SetButtonText(szBuf);
- SetStatus(NULL);
- }
- } /* ToOutline */
- /***************************************************************************
- * Function: ToMoved
- *
- * Purpose:
- *
- * If the user clicks on a MOVED line in expand mode, we jump to the
- * other line. We return TRUE if this was possible, or FALSE otherwise.
- */
- BOOL
- ToMoved(HWND hwnd)
- {
- BOOL bIsLeft;
- int linenr, state;
- long i, total;
- if (DisplayMode != MODE_EXPAND) {
- return(FALSE);
- }
- if (selection < 0) {
- return(FALSE);
- }
- state = view_getstate(current_view, selection);
- if (state == STATE_MOVEDLEFT) {
- bIsLeft = TRUE;
- /* get the linenr of the other copy */
- linenr = abs(view_getlinenr_right(current_view, selection));
- } else if (state == STATE_MOVEDRIGHT) {
- bIsLeft = FALSE;
- /* get the linenr of the other copy */
- linenr = abs(view_getlinenr_left(current_view, selection));
- } else {
- /* not a moved line - so we can't find another copy */
- return(FALSE);
- }
- /* search the view for this line nr */
- total = view_getrowcount(current_view);
- for (i = 0; i < total; i++) {
- if (bIsLeft) {
- if (linenr == view_getlinenr_right(current_view, i)) {
- /* found it */
- SetSelection(i);
- return(TRUE);
- }
- } else {
- if (linenr == view_getlinenr_left(current_view, i)) {
- SetSelection(i);
- return(TRUE);
- }
- }
- }
- return(FALSE);
- }
- /***************************************************************************
- * Function: do_editfile
- *
- * Purpose:
- *
- * Launch an editor on the current file (the file we are expanding, or
- * in outline mode the selected row. Option allows selection of the
- * left file, the right file or the composite view of this item.
- * pe points to a packet of parameters that must be freed before returning.
- * The return value is meaningless (just to conform to CreateThread).
- */
- LONG
- do_editfile(PEDITARGS pe)
- {
- VIEW view = pe->view;
- int option = pe->option;
- int selection = pe->selection;
- COMPITEM item;
- LPSTR fname;
- char cmdline[256];
- int currentline;
- char * pOut = cmdline;
- char * pIn = editor_cmdline;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- item = view_getitem(view, selection);
- if (item == NULL) {
- return -1;
- }
- fname = compitem_getfilename(item, option);
- if ( 0 == fname )
- {
- windiff_UI(TRUE);
- MessageBox(hwndClient, LoadRcString(IDS_FILE_DOESNT_EXIST),
- "Windiff", MB_ICONSTOP|MB_OK);
- windiff_UI(FALSE);
- goto error;
- }
- switch ( option )
- {
- case CI_LEFT:
- currentline = view_getlinenr_left( view,
- selection > 0 ? selection : 1);
- break;
- case CI_RIGHT:
- currentline = view_getlinenr_right( view,
- selection > 0 ? selection : 1);
- break;
- default:
- currentline = 1;
- break;
- }
- while( *pIn )
- {
- switch( *pIn )
- {
- case '%':
- pIn++;
- switch ( *pIn )
- {
- case 'p':
- lstrcpy( (LPTSTR)pOut, fname );
- while ( *pOut )
- pOut++;
- break;
- case 'l':
- _ltoa( currentline, pOut, 10 );
- while ( *pOut )
- pOut++;
- break;
- default:
- if (IsDBCSLeadByte(*pIn) && *(pIn+1)) {
- *pOut++ = *pIn++;
- }
- *pOut++ = *pIn;
- break;
- }
- pIn++;
- break;
- default:
- if (IsDBCSLeadByte(*pIn) && *(pIn+1)) {
- *pOut++ = *pIn++;
- }
- *pOut++ = *pIn++;
- break;
- }
- }
- /* Launch the process and waits for it to complete */
- si.cb = sizeof(STARTUPINFO);
- si.lpReserved = NULL;
- si.lpReserved2 = NULL;
- si.cbReserved2 = 0;
- si.lpTitle = (LPSTR)cmdline;
- si.lpDesktop = (LPTSTR)NULL;
- si.dwFlags = STARTF_FORCEONFEEDBACK;
- if (!CreateProcess(NULL,
- cmdline,
- NULL,
- NULL,
- FALSE,
- NORMAL_PRIORITY_CLASS,
- NULL,
- (LPTSTR)NULL,
- &si,
- &pi)) {
- windiff_UI(TRUE);
- MessageBox(hwndClient, LoadRcString(IDS_FAILED_TO_LAUNCH_EDT),
- "Windiff", MB_ICONSTOP|MB_OK);
- windiff_UI(FALSE);
- goto error;
- }
- /* wait for completion. */
- WaitForSingleObject(pi.hProcess, INFINITE);
- /* close process and thread handles */
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- /* finished with the filename. deletes it if it was a temp. */
- compitem_freefilename(item, option, fname);
- /*
- * refresh cached view always . A common trick is to edit the
- * composite file and then save it as a new left or right file.
- * Equally the user can edit the left and save as a new right.
- */
- /* We want to force both files to be re-read, but it's not a terribly
- * good idea to throw the lines away on this thread. Someone might
- * be reading them on another thread!
- */
- /* file_discardlines(compitem_getleftfile(item)) */
- /* file_discardlines(compitem_getrightfile(item)) */
- /* force the compare to be re-done */
- PostMessage(hwndClient, WM_COMMAND, IDM_UPDATE, (LONG)item);
- error:
- gmem_free(hHeap, (LPSTR) pe, sizeof(EDITARGS));
- return 0;
- } /* do_editfile */
- /***************************************************************************
- * Function: do_editthread
- *
- * Purpose:
- *
- * Launch an editor on a separate thread. It will actually get a separate
- * process, but we want our own thread in this process. This thread will
- * wait until it's finished and then order up a refresh of the UI.
- * Need to give it its parameters as a gmem allocated packet because
- * it IS on a separate thread.
- */
- void do_editthread(VIEW view, int option)
- {
- PEDITARGS pe;
- HANDLE thread;
- DWORD threadid;
- pe = (PEDITARGS) gmem_get(hHeap, sizeof(EDITARGS));
- pe->view = view;
- pe->option = option;
- pe->selection = selection;
- thread = CreateThread( NULL
- , 0
- , (LPTHREAD_START_ROUTINE)do_editfile
- , (LPVOID) pe
- , 0
- , &threadid
- );
- if (thread == NULL)
- {
- /* The createthread failed, do without the extra thread - just
- * call the function synchronously
- */
- do_editfile(pe);
- }
- else CloseHandle(thread);
- } /* do_editthread */
- /* status bar and busy flags --------------------------------------------*/
- /***************************************************************************
- * Function: SetButtonText
- *
- * Purpose:
- *
- * Set the Text on the statusbar button to reflect the current state
- */
- void
- SetButtonText(LPSTR cmd)
- {
- SendMessage(hwndStatus, SM_SETTEXT, IDM_ABORT, (DWORD) cmd);
- }
- /***************************************************************************
- * Function: SetStatus
- *
- * Purpose:
- *
- * Set the status field (left-hand part) of the status bar.
- */
- void
- SetStatus(LPSTR cmd)
- {
- SendMessage(hwndStatus, SM_SETTEXT, IDL_STATLAB, (DWORD) cmd);
- }
- /***************************************************************************
- * Function: SetNames
- *
- * Purpose:
- *
- * Set the names field - the central box in the status bar
- */
- void
- SetNames(LPSTR names)
- {
- SendMessage(hwndStatus, SM_SETTEXT, IDL_NAMES, (DWORD) names);
- if (names == NULL) {
- AppTitle[0] = ' ';
- } else {
- strncpy(AppTitle, names, sizeof(AppTitle));
- }
- }
- /***************************************************************************
- * Function: SetBusy
- *
- * Purpose:
- *
- * If we are not already busy, set the busy flag.
- *
- * Enter critical section first.
- */
- BOOL
- SetBusy(void)
- {
- HMENU hmenu;
- WDEnter();
- if (fBusy) {
- WDLeave();
- return(FALSE);
- }
- fBusy = TRUE;
- SetStatus(LoadRcString(IDS_COMPARING));
- /* status also on window text, so that you can see even from
- * the icon when the scan has finished
- */
- SetWindowText(hwndClient, LoadRcString(IDS_SCANNING));
- /* disable appropriate parts of menu */
- hmenu = GetMenu(hwndClient);
- EnableMenuItem(hmenu, IDM_FILE,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
- EnableMenuItem(hmenu, IDM_DIR,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
- EnableMenuItem(hmenu, IDM_PRINT,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
- /* enable abort only when busy */
- EnableMenuItem(hmenu, IDM_ABORT,MF_ENABLED|MF_BYCOMMAND);
- SetButtonText(LoadRcString(IDS_ABORT)); /* leave DisplayMode unchanged */
- WDLeave();
- return(TRUE);
- } /* SetBusy */
- /***************************************************************************
- * Function: SetNotBusy
- *
- * Purpose:
- *
- * This function can be called from the worker thread.
- * Thus we must not cause any SendMessage calls to windows
- * owned by the main thread while holding the CritSec or we
- * could cause deadlock.
- *
- * The critsec is only needed to protect the fBusy flag - so
- * clear the busy flag last, and only get the crit sec as needed.
- */
- void
- SetNotBusy(void)
- {
- HMENU hmenu;
- /* reset button and status bar (clearing out busy flags) */
- if (current_view == NULL) {
- SetButtonText(LoadRcString(IDS_EXIT));
- SetStatus(NULL);
- DisplayMode = MODE_NULL;
- } else if (view_isexpanded(current_view)) {
- TCHAR szBuf[10];
- lstrcpy(szBuf,LoadRcString(IDS_OUTLINE));
- SetButtonText(szBuf);
- SetStatus(view_getcurrenttag(current_view) );
- DisplayMode = MODE_EXPAND;
- } else {
- TCHAR szBuf[8];
- lstrcpy(szBuf,LoadRcString(IDS_EXPAND));
- SetButtonText(szBuf);
- SetStatus(NULL);
- DisplayMode = MODE_OUTLINE;
- }
- SetWindowText(hwndClient, "WinDiff");
- /* re-enable appropriate parts of menu */
- hmenu = GetMenu(hwndClient);
- EnableMenuItem(hmenu, IDM_FILE,MF_ENABLED|MF_BYCOMMAND);
- EnableMenuItem(hmenu, IDM_DIR,MF_ENABLED|MF_BYCOMMAND);
- EnableMenuItem(hmenu, IDM_PRINT,MF_ENABLED|MF_BYCOMMAND);
- /* disable abort now no longer busy */
- EnableMenuItem(hmenu, IDM_ABORT,MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
- /* clear the busy flag, protected by critical section */
- WDEnter();
- fBusy = FALSE;
- bAbort = FALSE;
- if (ghThread!=NULL){
- CloseHandle(ghThread);
- ghThread = NULL;
- }
- WDLeave();
- } /* SetNotBusy */
- /***************************************************************************
- * Function: IsBusy
- *
- * Purpose:
- *
- * Checks whether or not crit sec is open
- */
- BOOL
- IsBusy()
- {
- BOOL bOK;
- WDEnter();
- bOK = fBusy;
- WDLeave();
- return(bOK);
- } /* IsBusy */
- /***************************************************************************
- * Function: BusyError
- *
- * Purpose:
- *
- * Puts up message box that system is busy.
- */
- void
- BusyError(void)
- {
- windiff_UI(TRUE);
- MessageBox(hwndClient,
- LoadRcString(IDS_PLEASE_WAIT),
- "WinDiff", MB_OK|MB_ICONSTOP);
- windiff_UI(FALSE);
- } /* BusyError */
- /* --- colour scheme --------------------------------------------------- */
- /***************************************************************************
- * Function: StateToColour
- *
- * Purpose:
- *
- * Map the state given into a foreground and a background colour
- * for states that are highlighted. Return P_FCOLOUR if the foreground
- * colour (put in *foreground) is to be used, return P_FCOLOUR|P_BCOLOUR if
- * both *foreground and *background are to be used, or 0 if the default
- * colours are to be used.
- */
- UINT
- StateToColour(int state, int col, DWORD FAR * foreground, DWORD FAR * background)
- {
- switch (state) {
- case STATE_DIFFER:
- /* files that differ are picked out in a foreground highlight,
- * with the default background
- */
- *foreground = rgb_outlinehi;
- return(P_FCOLOUR);
- case STATE_LEFTONLY:
- /* lines only in the left file */
- *foreground = rgb_leftfore;
- *background = rgb_leftback;
- return(P_FCOLOUR|P_BCOLOUR);
- case STATE_RIGHTONLY:
- /* lines only in the right file */
- *foreground = rgb_rightfore;
- *background = rgb_rightback;
- return(P_FCOLOUR|P_BCOLOUR);
- case STATE_MOVEDLEFT:
- /* displaced lines in both files - left file version */
- *foreground = rgb_mleftfore;
- *background = rgb_mleftback;
- return(P_FCOLOUR|P_BCOLOUR);
- case STATE_MOVEDRIGHT:
- /* displaced lines in both files - right file version */
- *foreground = rgb_mrightfore;
- *background = rgb_mrightback;
- return(P_FCOLOUR|P_BCOLOUR);
- default:
- /* no highlighting - default colours */
- return(0);
- }
- }
- /* table window communication routines ---------------------------------*/
- /***************************************************************************
- * Function: SetSelection
- *
- * Purpose:
- *
- * Set a given row as the selected row in the table window
- */
- void
- SetSelection(long rownr)
- {
- TableSelection select;
- select.startrow = rownr;
- select.startcell = 0;
- select.nrows = 1;
- select.ncells = 1;
- SendMessage(hwndRCD, TM_SELECT, 0, (long) (LPSTR)&select);
- }
- /***************************************************************************
- * Function: do_gethdr
- *
- * Purpose:
- *
- * Handle table class call back to get nr of rows and columns,
- * and properties for the whole table.
- * The 'table id' is either TABID_PRINTER - meaning we are
- * printing the current_view, or it is the view to
- * use for row/column nr information
- */
- long
- do_gethdr(HWND hwnd, lpTableHdr phdr)
- {
- VIEW view;
- BOOL bIsPrinter = FALSE;
- if (phdr->id == TABID_PRINTER) {
- view = current_view;
- bIsPrinter = TRUE;
- } else {
- view = (VIEW) phdr->id;
- }
- if (view == NULL) {
- return(FALSE);
- }
- phdr->nrows = view_getrowcount(view);
- /* three columns: line nr, tag and rest of line */
- /*
- * if IDM_NONRS (no line numbers) is selected, suppress the
- * line-nr column entirely to save screen space
- */
- if (line_numbers == IDM_NONRS) {
- phdr->ncols = 2;
- phdr->fixedcols = 0;
- } else {
- phdr->ncols = 3;
- phdr->fixedcols = 1;
- }
- phdr->fixedrows = 0;
- phdr->fixedselectable = FALSE;
- phdr->hseparator = TRUE;
- phdr->vseparator = TRUE;
- phdr->selectmode = TM_ROW | TM_SINGLE;
- /*
- * find if we are in expand mode - ask for the item we are expanding.
- */
- if (view_isexpanded(view) == TRUE) {
- /* use focus rect as selection mode in expand mode
- * so as not to interfere with background colours.
- */
- phdr->selectmode |= TM_FOCUS;
- } else {
- /* use default solid inversion when possible as it is clearer.*/
- phdr->selectmode |= TM_SOLID;
- }
- /* please send TQ_SCROLL notifications when the table is scrolled */
- phdr->sendscroll = TRUE;
- phdr->props.valid = 0;
- return TRUE;
- }
- /***************************************************************************
- * Function: do_getprops
- *
- * Purpose:
- *
- * Respond to table callback asking for the size and properties
- * of each column. Table id is either TABID_PRINTER (meaning the
- * current_view, for printing) or it is the view to be used.
- */
- long
- do_getprops(HWND hwnd, lpColPropsList propslist)
- {
- int i, cell;
- BOOL bIsPrinter = FALSE;
- VIEW view;
- if (propslist->id == TABID_PRINTER) {
- view = current_view;
- bIsPrinter = TRUE;
- } else {
- view = (VIEW) propslist->id;
- }
- if (view == NULL) {
- return(FALSE);
- }
- /* The table inteface is slightly confused here. we are not
- * guaranteed which columns we are being asked about, so instead
- * of just setting each column cols[0], cols[1] etc, we need
- * to loop through, looking at each column in the table and
- * seeing which it is.
- */
- for (i = 0; i < propslist->ncols; i++) {
- cell = i + propslist->startcol;
- propslist->plist[i].props.valid = 0;
- /* for all column widths, add on 1 for the NULL char. */
- /*
- * skip the line nr column if IDM_NONRS
- */
- if (line_numbers == IDM_NONRS) {
- cell++;
- }
- if (cell == 0) {
- /* properties for line nr column */
- propslist->plist[i].nchars = view_getwidth(view, 0)+1;
- propslist->plist[i].props.valid |= P_ALIGN;
- propslist->plist[i].props.alignment = P_CENTRE;
- } else if (cell == 1) {
- /* properties for tag field */
- propslist->plist[i].nchars = view_getwidth(view, 1)+1;
- propslist->plist[i].props.valid |= P_ALIGN;
- propslist->plist[i].props.alignment = P_LEFT;
- } else {
- /* properties for main text column -
- * use a fixed font unless printing (if
- * printing, best to use the default font, because
- * of resolution differences.
- * add on 8 chars to the width to ensure that
- * the width of lines beginning with tabs
- * works out ok
- */
- propslist->plist[i].nchars = view_getwidth(view, 2)+1;
- propslist->plist[i].props.valid |= P_ALIGN;
- propslist->plist[i].props.alignment = P_LEFT;
- if (!bIsPrinter) {
- propslist->plist[i].props.valid |= P_FONT;
- propslist->plist[i].props.hFont =
- GetStockObject(SYSTEM_FIXED_FONT);
- }
- }
- }
- return (TRUE);
- }
- /***************************************************************************
- * Function: do_getdata
- *
- * Purpose:
- *
- * Respond to a table callback asking for the contents of individual cells.
- * table id is either TABID_PRINTER, or it is a pointer to the view
- * to use for data. If going to the printer, don't set the
- * colours (stick to black and white).
- */
- long
- do_getdata(HWND hwnd, lpCellDataList cdlist)
- {
- int start, endcell, col, i;
- lpCellData cd;
- VIEW view;
- LPSTR textp;
- BOOL bIsPrinter = FALSE;
- if (cdlist->id == TABID_PRINTER) {
- view = current_view;
- bIsPrinter = TRUE;
- } else {
- view = (VIEW) cdlist->id;
- }
- start = cdlist->startcell;
- endcell = cdlist->ncells + start;
- if (cdlist->row >= view_getrowcount(view)) {
- return(FALSE);
- }
- for (i = start; i < endcell; i++) {
- cd = &cdlist->plist[i - start];
- /* skip the line number column if IDM_NONRS */
- if (line_numbers == IDM_NONRS) {
- col = i+1;
- } else {
- col = i;
- }
- /* set colour of text to mark out
- * lines that are changed, if not printer - for the
- * printer everything should stay in the default colours
- */
- if (!bIsPrinter) {
- /* convert the state of the requested row into a
- * colour scheme. returns P_FCOLOUR and/or
- * P_BCOLOUR if it sets either of the colours
- */
- cd->props.valid |=
- StateToColour(view_getstate(view, cdlist->row), col,
- &cd->props.forecolour,
- &cd->props.backcolour);
- }
- textp = view_gettext(view, cdlist->row, col);
- if (cd->nchars != 0) {
- if (textp == NULL) {
- cd->ptext[0] = ' ';
- } else {
- strncpy(cd->ptext, textp, cd->nchars -1);
- cd->ptext[cd->nchars - 1] = ' ';
- }
- }
- }
- return(TRUE);
- }
- /***************************************************************************
- * Function: SvrClose
- *
- * Purpose:
- *
- * Table window has finished with this view. It can be deleted.
- */
- void
- SvrClose(void)
- {
- view_delete(current_view);
- current_view = NULL;
- /* hide picture - only visible when we are in MODE_EXPAND */
- DisplayMode = MODE_NULL;
- DoResize(hwndClient);
- /* if we already busy when closing this view (ie
- * we are in the process of starting a new scan,
- * then leave the status bar alone, otherwise
- * we should clean up the state of the status bar
- */
- if (!fBusy) {
- SetButtonText(LoadRcString(IDS_EXIT));
- SetNames(NULL);
- SetStatus(NULL);
- }
- } /* SvrClose */
- /***************************************************************************
- * Function: TableServer
- *
- * Purpose:
- *
- * Handle callbacks and notifications from the table class
- */
- long
- TableServer(HWND hwnd, UINT cmd, long lParam)
- {
- lpTableHdr phdr;
- lpColPropsList proplist;
- lpCellDataList cdlist;
- lpTableSelection pselect;
- switch(cmd) {
- case TQ_GETSIZE:
- /* get the nr of rows and cols in this table */
- phdr = (lpTableHdr) lParam;
- return(do_gethdr(hwnd, phdr));
- case TQ_GETCOLPROPS:
- /* get the size and properties of each column */
- proplist = (lpColPropsList) lParam;
- return (do_getprops(hwnd, proplist));
- case TQ_GETDATA:
- /* get the contents of individual cells */
- cdlist = (lpCellDataList) lParam;
- return (do_getdata(hwnd, cdlist));
- case TQ_SELECT:
- /* selection has changed */
- case TQ_ENTER:
- /* user has double-clicked or pressed enter */
- pselect = (lpTableSelection) lParam;
- /* store location for use in later search (IDM_FCHANGE) */
- if (pselect->nrows < 1) {
- selection = -1;
- } else {
- selection = (int) pselect->startrow;
- if (cmd == TQ_ENTER) {
- /* try to expand this row */
- if (!ToExpand(hwnd)) {
- /* expand failed - maybe this
- * is a moved line- show the other
- * copy
- */
- ToMoved(hwnd);
- }
- }
- }
- break;
- case TQ_CLOSE:
- /* close this table - table class no longer needs data*/
- SvrClose();
- break;
- case TQ_SCROLL:
- /* notification that the rows visible in the window
- * have changed -change the current position lines in
- * the graphic bar view (the sections picture)
- */
- if (picture_mode) {
- BarDrawPosition(hwndBar, NULL, TRUE);
- }
- break;
- default:
- return(FALSE);
- }
- return(TRUE);
- }
- /***************************************************************************
- * Function: wd_initial
- *
- * Purpose:
- *
- * Called on worker thread (not UI thread) to handle the work
- * requested on the command line.
- * arg is a pointer to a THREADARGS block allocated from gmem_get(hHeap). This
- * needs to be freed before exiting.
- */
- DWORD
- wd_initial(LPVOID arg)
- {
- PTHREADARGS pta = (PTHREADARGS) arg;
- COMPLIST cl;
- /* build a complist from these args,
- * and register with the view we have made
- */
- cl = complist_args(pta->first, pta->second, pta->view, pta->fDeep);
- if (cl == NULL) {
- view_close(pta->view);
- gmem_free(hHeap, (LPSTR) pta, sizeof(THREADARGS));
- SetNotBusy();
- return 0;
- }
- /* if savelist was selected, write out the list and exit */
- if(pta->savelist != NULL) {
- complist_savelist(cl, pta->savelist, pta->saveopts);
- gmem_free(hHeap, (LPSTR) pta, sizeof(THREADARGS));
- SetNotBusy();
- exit(0);
- }
- /* if there was only one file, expand it */
- if (view_getrowcount(pta->view) == 1) {
- SetSelection(0);
- ToExpand(hwndClient);
- }
- gmem_free(hHeap, (LPSTR) pta, sizeof(THREADARGS));
- SetNotBusy();
- return(0);
- } /* wd_initial */
- /***************************************************************************
- * Function: wd_dirdialog
- *
- * Purpose:
- *
- * Called on worker thread (not UI thread) to handle a Dir request
- */
- DWORD
- wd_dirdialog(LPVOID arg)
- {
- VIEW view = (VIEW) arg;
- /* make a COMPLIST using the directory dialog,
- * and notify the view
- */
- if (complist_dirdialog(view) == NULL) {
- view_close(view);
- }
- /* all done! */
- SetNotBusy();
- return(0);
- }
- /***************************************************************************
- * Function: wd_copy
- *
- * Purpose:
- *
- * Called on worker thread to do a copy-files operation
- */
- DWORD
- wd_copy(LPVOID arg)
- {
- VIEW view = (VIEW) arg;
- complist_copyfiles(view_getcomplist(view), NULL, 0);
- SetNotBusy();
- return(0);
- }
- /***************************************************************************
- * Function: MainWndProc
- *
- * Purpose:
- *
- * Window processing for main window
- */
- long APIENTRY
- MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
- {
- char str[32];
- long ret;
- DWORD threadid;
- switch(message) {
- case WM_CREATE:
- /* initialise menu options to default/saved
- * option settings
- */
- CheckMenuItem(hMenu, IDM_INCSAME,
- (outline_include & INCLUDE_SAME) ?
- MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hMenu, IDM_INCLEFT,
- (outline_include & INCLUDE_LEFTONLY) ?
- MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hMenu, IDM_INCRIGHT,
- (outline_include & INCLUDE_RIGHTONLY) ?
- MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hMenu, IDM_INCDIFFER,
- (outline_include & INCLUDE_DIFFER) ?
- MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hMenu, line_numbers, MF_CHECKED);
- CheckMenuItem(hMenu, expand_mode, MF_CHECKED);
- CheckMenuItem(hMenu, IDM_IGNBLANKS,
- ignore_blanks ? MF_CHECKED : MF_UNCHECKED);
- CheckMenuItem(hMenu, IDM_PICTURE,
- picture_mode ? MF_CHECKED : MF_UNCHECKED);
- /* nothing currently displayed */
- DisplayMode = MODE_NULL;
- break;
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam)) {
- case IDM_EXIT:
- if (ghThread!=NULL) {
- extern CRITICAL_SECTION CSView;
- /* Stop any other thread from allocating things that we
- want to free! See the threads DOGMA at the top
- of this file.
- */
- /* Because the thread that we are about to kill might be in
- a critical section, we first grab them both. It is
- essential that anyone else who ever does this, does
- so in the same order!
- */
- WDEnter();
- EnterCriticalSection(&CSView);
- TerminateThread(ghThread, 31);
- CloseHandle(ghThread);
- ghThread = NULL;
- LeaveCriticalSection(&CSView);
- WDLeave();
- }
- if (!view_isexpanded(current_view)) {
- /* save the current outline size and position */
- WINDOWPLACEMENT wp;
- if (GetWindowPlacement(hwndClient,&wp)) {
- WriteProfileInt(APPNAME, "OutlineShowCmd", wp.showCmd);
- WriteProfileInt(APPNAME, "OutlineMaxX", wp.ptMaxPosition.x);
- WriteProfileInt(APPNAME, "OutlineMaxY", wp.ptMaxPosition.y);
- WriteProfileInt(APPNAME, "OutlineNormLeft", wp.rcNormalPosition.left);
- WriteProfileInt(APPNAME, "OutlineNormTop", wp.rcNormalPosition.top);
- WriteProfileInt(APPNAME, "OutlineNormRight", wp.rcNormalPosition.right);
- WriteProfileInt(APPNAME, "OutlineNormBottom", wp.rcNormalPosition.bottom);
- WriteProfileInt(APPNAME, "OutlineSaved", 1);
- }
- } else {
- /* save the current expanded size and position */
- WINDOWPLACEMENT wp;
- if (GetWindowPlacement(hwndClient,&wp)) {
- WriteProfileInt(APPNAME, "ExpandShowCmd", wp.showCmd);
- WriteProfileInt(APPNAME, "ExpandMaxX", wp.ptMaxPosition.x);
- WriteProfileInt(APPNAME, "ExpandMaxY", wp.ptMaxPosition.y);
- WriteProfileInt(APPNAME, "ExpandNormLeft", wp.rcNormalPosition.left);
- WriteProfileInt(APPNAME, "ExpandNormTop", wp.rcNormalPosition.top);
- WriteProfileInt(APPNAME, "ExpandNormRight", wp.rcNormalPosition.right);
- WriteProfileInt(APPNAME, "ExpandNormBottom", wp.rcNormalPosition.bottom);
- WriteProfileInt(APPNAME, "ExpandedSaved", 1);
- }
- }
- DestroyWindow(hWnd);
- break;
- case IDM_ABORT:
- /* abort menu item, or status bar button.
- * the status bar button text gives the appropriate
- * action depending on our state - abort, outline
- * or expand. But the command sent is always
- * IDM_ABORT. Thus we need to check the state
- * to see what to do. If we are busy, set the abort
- * flag. If there is nothing to view,
- * exit, otherwise switch outline<->expand
- */
- if (IsBusy()) {
- bAbort = TRUE;
- SetStatus(LoadRcString(IDS_ABORT_PENDING));
- } else if (DisplayMode == MODE_NULL) {
- DestroyWindow(hWnd);
- } else if (DisplayMode == MODE_EXPAND) {
- ToOutline(hWnd);
- } else {
- ToExpand(hWnd);
- }
- break;
- case IDM_FILE:
- /* select two files and compare them */
- if (SetBusy()) {
- /* close the current view */
- view_close(current_view);
- /* make a new empty view */
- current_view = view_new(hwndRCD);
- /* make a COMPLIST using the files dialog,
- * and notify the view
- */
- if (complist_filedialog(current_view) == NULL) {
- view_close(current_view);
- }
- /* all done! */
- SetNotBusy();
- } else {
- BusyError();
- }
- break;
- case IDM_DIR:
- /* read two directory names, scan them and
- * compare all the files and subdirs.
- */
- if (SetBusy()) {
- /* close the current view */
- view_close(current_view);
- /* make a new empty view */
- current_view = view_new(hwndRCD);
- ghThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wd_dirdialog,
- (LPVOID) current_view, 0, &threadid);
- if (ghThread == NULL)
- {
- wd_dirdialog( (LPVOID) current_view);
- }
- } else {
- BusyError();
- }
- break;
- case IDM_CLOSE:
- /* close the output list -
- * discard all results so far
- */
- if (!IsBusy()) {
- view_close(current_view);
- }
- break;
- case IDM_PRINT:
- /* print the current view -
- * either the outline list of filenames,
- * or the currently expanded file.
- */
- if (!IsBusy()) {
- DoPrint();
- } else {
- BusyError();
- }
- break;
- case IDM_TIME:
- /* show time it took */
- { char msg[50];
- DWORD tim;
- if (IsBusy()) {
- BusyError();
- }
- else{
- tim = complist_querytime();
- wsprintf((LPTSTR)msg, LoadRcString(IDS_SECONDS), tim/1000, tim%1000);
- }
- }
- break;
- case IDM_SAVELIST:
- /* allow user to save list of same/different files
- * to a text file. dialog box to give filename
- * and select which types of file to include
- */
- complist_savelist(view_getcomplist(current_view), NULL, 0);
- break;
- case IDM_COPYFILES:
- /*
- * copy files that are same/different to a new
- * root directory. dialog box allows user
- * to select new root and inclusion options
- */
- if (current_view == NULL) {
- MessageBox(hWnd,
- LoadRcString(IDS_CREATE_DIFF_LIST),
- "WinDiff", MB_OK|MB_ICONSTOP);
- break;
- }
- if (SetBusy()) {
- ghThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wd_copy,
- (LPVOID) current_view, 0, &threadid);
- if (ghThread == NULL)
- {
- wd_copy( (LPVOID) current_view);
- }
- } else {
- BusyError();
- }
- break;
- case IDM_ABOUT:
- DialogBox( hInst, "About", hWnd, (DLGPROC)AboutBox);
- break;
- /* launch an editor on the current item - left, right or
- * composite view
- */
- case IDM_EDITLEFT:
- do_editthread(current_view, CI_LEFT);
- break;
- case IDM_EDITRIGHT:
- do_editthread(current_view, CI_RIGHT);
- break;
- case IDM_EDITCOMP:
- do_editthread(current_view, CI_COMP);
- break;
- /* allow customisation of the editor command line */
- case IDM_SETEDIT:
- if (StringInput(editor_cmdline, sizeof(editor_cmdline),
- LoadRcString(IDS_ENTER_EDT_CMD_LINE),
- "Windiff", editor_cmdline)) {
- WriteProfileString(APPNAME, "Editor",
- (LPCSTR)editor_cmdline);
- }
- break;
- case IDM_LNRS:
- case IDM_RNRS:
- case IDM_NONRS:
- /* option selects whether the line nrs displayed
- * in expand mode are the line nrs in the left
- * file, the right file or none
- */
- CheckMenuItem(GetMenu(hWnd),
- line_numbers, MF_UNCHECKED);
- line_numbers = GET_WM_COMMAND_ID(wParam, lParam);
- CheckMenuItem(GetMenu(hWnd), line_numbers, MF_CHECKED);
- wsprintf((LPTSTR)str, "%d", line_numbers);
- WriteProfileString(APPNAME, "LineNumbers", str);
- /* change the display to show the line nr style
- * chosen
- */
- view_changeviewoptions(current_view);
- break;
- /*
- * options selecting which files to include in the
- * outline listing, based on their state
- */
- case IDM_INCLEFT:
- /* toggle flag in outline_include options */
- outline_include ^= INCLUDE_LEFTONLY;
- /* check/uncheck as necessary */
- CheckMenuItem(hMenu, IDM_INCLEFT,
- (outline_include & INCLUDE_LEFTONLY) ?
- MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", outline_include);
- WriteProfileString(APPNAME, "FileInclude", str);
- view_changeviewoptions(current_view);
- break;
- case IDM_INCRIGHT:
- outline_include ^= INCLUDE_RIGHTONLY;
- CheckMenuItem(hMenu, IDM_INCRIGHT,
- (outline_include & INCLUDE_RIGHTONLY) ?
- MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", outline_include);
- WriteProfileString(APPNAME, "FileInclude", str);
- view_changeviewoptions(current_view);
- break;
- case IDM_INCSAME:
- outline_include ^= INCLUDE_SAME;
- CheckMenuItem(hMenu, IDM_INCSAME,
- (outline_include & INCLUDE_SAME) ?
- MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", outline_include);
- WriteProfileString(APPNAME, "FileInclude", str);
- view_changeviewoptions(current_view);
- break;
- case IDM_INCDIFFER:
- outline_include ^= INCLUDE_DIFFER;
- CheckMenuItem(hMenu, IDM_INCDIFFER,
- (outline_include & INCLUDE_DIFFER) ?
- MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", outline_include);
- WriteProfileString(APPNAME, "FileInclude", str);
- view_changeviewoptions(current_view);
- break;
- case IDM_UPDATE:
- /* update the display. Options or files may have changed */
- /* discard lines (thereby forcing re-read).
- */
- file_discardlines(compitem_getleftfile( (COMPITEM)lParam) );
- file_discardlines(compitem_getrightfile( (COMPITEM)lParam) );
- view_changediffoptions(current_view);
- /* force repaint of bar window */
- InvalidateRect(hwndBar, NULL, TRUE);
- break;
- case IDM_LONLY:
- case IDM_RONLY:
- case IDM_BOTHFILES:
- /* option selects whether the expanded file
- * show is the combined file, or just one
- * or other of the input files.
- *
- * if we are not in expand mode, this also
- * causes us to expand the selection
- */
- CheckMenuItem(GetMenu(hWnd), expand_mode, MF_UNCHECKED);
- expand_mode = GET_WM_COMMAND_ID(wParam, lParam);
- CheckMenuItem(GetMenu(hWnd), expand_mode, MF_CHECKED);
- /* change the current view to show only the lines
- * of the selected type.
- */
- if (DisplayMode == MODE_OUTLINE) {
- ToExpand(hWnd);
- } else {
- view_changeviewoptions(current_view);
- }
- break;
- case IDM_IGNBLANKS:
- /* if selected, ignore all spaces and tabs on
- * comparison - expand view only: outline view
- * will still show that 'text files differ'
- */
- ignore_blanks = !ignore_blanks;
- CheckMenuItem(hMenu, IDM_IGNBLANKS,
- ignore_blanks? MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", ignore_blanks);
- WriteProfileString(APPNAME, "Blanks", str);
- /* invalidate all diffs since we have
- * changed diff options, and re-do and display the
- * current diff if we are in expand mode.
- */
- view_changediffoptions(current_view);
- /* force repaint of bar window */
- InvalidateRect(hwndBar, NULL, TRUE);
- break;
- case IDM_PICTURE:
- /* do we show the bar picture in expand mode ? */
- picture_mode = !picture_mode;
- CheckMenuItem(hMenu, IDM_PICTURE,
- picture_mode? MF_CHECKED:MF_UNCHECKED);
- wsprintf((LPTSTR)str, "%d", picture_mode);
- WriteProfileString(APPNAME, "Picture", str);
- DoResize(hWnd);
- break;
- case IDM_EXPAND:
- /* show the expanded view of the
- * selected file
- */
- if (current_view != NULL) {
- ToExpand(hWnd);
- }
- break;
- case IDM_OUTLINE:
- /* return to the outline view (list of filenames) */
- ToOutline(hWnd);
- break;
- case IDM_FCHANGE:
- /* find the next line in the current view
- * that is not the same in both files -
- * in outline view, finds the next filename that
- * is not identical
- */
- FindNextChange();
- break;
- case IDM_FPCHANGE:
- /* same as IDM_FCHANGE, but going backwards from
- * current position
- */
- FindPrevChange();
- break;
- }
- break;
- case WM_SIZE:
- DoResize(hWnd);
- break;
- case WM_SETFOCUS:
- /* set the focus on the table class so it can process
- * page-up /pagedown keys etc.
- */
- SetFocus(hwndRCD);
- break;
- case WM_KEYDOWN:
- /* although the table window has the focus, he passes
- * back to us any keys he doesn't understand
- * We handle escape here to mean 'return to outline view'
- */
- if (wParam == VK_ESCAPE) {
- ToOutline(hWnd);
- }
- break;
- case WM_CLOSE:
- /* don't allow close when busy - process this message in
- * order to ensure this
- */
- if (IsBusy()) {
- return(TRUE);
- } else {
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- break;
- case WM_DESTROY:
- DeleteTools();
- PostQuitMessage(0);
- break;
- case TM_CURRENTVIEW:
- /* allow other people such as the bar window to query the
- * current view
- */
- return((DWORD) current_view);
- default:
- /* handle registered table messages */
- if (message == table_msgcode) {
- ret = TableServer(hWnd, wParam, lParam);
- return(ret);
- }
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- return(0);
- }
- /***************************************************************************
- * Function: My_mbschr
- *
- * Purpose:
- *
- * DBCS version of strchr
- *
- */
- unsigned char * _CRTAPI1 My_mbschr(
- unsigned char *psz, unsigned short uiSep)
- {
- while (*psz != ' ' && *psz != uiSep) {
- psz = CharNext(psz);
- }
- return *psz == uiSep ? psz : NULL;
- }
- /***************************************************************************
- * Function: My_mbsncpy
- *
- * Purpose:
- *
- * DBCS version of strncpy
- *
- */
- unsigned char * _CRTAPI1 My_mbsncpy(
- unsigned char *psz1, const unsigned char *psz2, size_t Length)
- {
- int nLen = (int)Length;
- unsigned char *pszSv = psz1;
- while (0 < nLen) {
- if (*psz2 == ' ') {
- *psz1++ = ' ';
- nLen--;
- } else if (IsDBCSLeadByte(*psz2)) {
- if (nLen == 1) {
- *psz1 = ' ';
- } else {
- *psz1++ = *psz2++;
- *psz1++ = *psz2++;
- }
- nLen -= 2;
- } else {
- *psz1++ = *psz2++;
- nLen--;
- }
- }
- return pszSv;
- }
- /***************************************************************************
- * Function: My_mbsrchr
- *
- * Purpose:
- *
- * DBCS version of strrchr
- *
- */
- unsigned char * _CRTAPI1 My_mbsrchr(
- unsigned char *psz, unsigned short uiSep)
- {
- unsigned char *pszHead;
- pszHead = psz;
- while (*psz != ' ') {
- psz++;
- }
- if (uiSep == ' ') {
- return psz;
- }
- while (psz > pszHead) {
- psz = CharPrev(pszHead, psz);
- if (*psz == uiSep) {
- break;
- }
- }
- return *psz == uiSep ? psz : NULL;
- }
- /***************************************************************************
- * Function: My_mbsncmp
- *
- * Purpose:
- *
- * DBCS version of strncmp
- * If 'nLen' splits a DBC, this function compares the DBC's 2nd byte also.
- *
- */
- int _CRTAPI1 My_mbsncmp(
- const unsigned char *psz1, const unsigned char *psz2, size_t nLen)
- {
- int Length = (int)nLen;
- while (0 < Length) {
- if (' ' == *psz1 || ' ' == *psz2) {
- return *psz1 - *psz2;
- }
- if (IsDBCSLeadByte(*psz1) || IsDBCSLeadByte(*psz2)) {
- if (*psz1 != *psz2 || *(psz1+1) != *(psz2+1)) {
- return *psz1 - *psz2;
- }
- psz1 += 2;
- psz2 += 2;
- Length -= 2;
- } else {
- if (*psz1 != *psz2) {
- return *psz1 - *psz2;
- }
- psz1++;
- psz2++;
- Length--;
- }
- }
- return 0;
- }