home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * 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: BAR.C
- *
- * This module contains functions for bar window
- * graphically showing two lists of sections and showing
- * colored vertical bars for the sections of text,
- * with linking lines for the sections that are the same.
- *
- * Functions:
- *
- * BarWndProc()
- * BarPaint()
- * DrawSection()
- * DrawLink()
- * BarClick()
- * InitBarClass()
- * BarDrawPosition()
- *
- * Comments:
- *
- ****************************************************************************/
-
- #include <windows.h>
- #include <commdlg.h>
-
- #include "gutils.h"
- #include "table.h"
- #include "state.h"
- #include "wdiffrc.h"
- #include "windiff.h"
- #include "list.h"
- #include "line.h"
- #include "scandir.h"
- #include "file.h"
- #include "section.h"
- #include "compitem.h"
- #include "complist.h"
- #include "view.h"
-
-
- long APIENTRY BarWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam);
- void BarPaint(HWND hwnd);
- void DrawSection(HDC hdc, int cx, int cy, int lines, SECTION sec, int sidecode);
- void DrawLink(HDC hdc, int cx, int cy, int lines, SECTION sec);
- void BarClick(HWND hwnd, int x, int y);
-
-
- HPEN hpenSame, hpenLeft, hpenRight;
- HBRUSH hbrSame, hbrLeft, hbrRight;
- HBRUSH hbrSideBar;
-
-
- /***************************************************************************
- * Function: InitBarClass
- *
- * Purpose:
- *
- * Create bar window class
- */
- BOOL
- InitBarClass(HINSTANCE hInstance)
- {
- WNDCLASS wc;
- BOOL resp;
-
-
-
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = BarWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszClassName = "BarClass";
- wc.lpszMenuName = NULL;
-
- resp = RegisterClass(&wc);
-
- return(resp);
- }
-
-
-
- /***************************************************************************
- * Function: BarWndProc
- *
- * Purpose:
- *
- * Window procedure supporting bar window
- *
- */
-
- long APIENTRY
- BarWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
- {
-
- switch(message) {
-
-
- case WM_CREATE:
-
- hpenSame = CreatePen(PS_SOLID, 1, RGB(0,0,0));
- hbrSame = CreateSolidBrush(RGB(255,255,255));
-
- hpenLeft = CreatePen(PS_SOLID, 1, rgb_barleft);
- hbrLeft = CreateSolidBrush(rgb_barleft);
-
- hpenRight = CreatePen(PS_SOLID, 1, rgb_barright);
- hbrRight = CreateSolidBrush(rgb_barright);
-
- hbrSideBar = CreateSolidBrush(rgb_barcurrent);
- break;
-
- case WM_DESTROY:
- DeleteObject(hpenSame);
- DeleteObject(hpenLeft);
- DeleteObject(hpenRight);
- DeleteObject(hbrSame);
- DeleteObject(hbrLeft);
- DeleteObject(hbrRight);
- DeleteObject(hbrSideBar);
- break;
-
- case WM_PAINT:
- BarPaint(hWnd);
- break;
-
- case WM_LBUTTONDOWN:
- BarClick(hWnd, LOWORD(lParam), HIWORD(lParam));
- break;
-
- default:
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- return 0;
- }
-
- /***************************************************************************
- * Function: BarDrawPosition
- *
- * Purpose:
- *
- * Draw the current position as side-bars down the bar window,
- * showing which lines from each file are currently in view. HDC can be
- * NULL (we get one ourselves if so). If bErase is true, we clear
- * the previous side-bars first.
- *
- * This is called from BarPaint when we paint the whole window, and
- * from TableServer() whenever it receives a TQ_SCROLL notification that
- * the table window has been scrolled.
- */
- void
- BarDrawPosition(HWND hwndBar, HDC hdcIn, BOOL bErase)
- {
- HDC hdc;
- int total_lines, cy, cx;
- RECT rc, rcLeft, rcRight;
- VIEW view;
- COMPITEM item;
- LIST listleft, listright;
- long toprow, endrow, i;
- int left_first, left_last, right_first, right_last, linenr;
-
-
- /* get a hdc if we weren't given one */
- if (hdcIn == NULL) {
- hdc = GetDC(hwndBar);
- } else {
- hdc = hdcIn;
- }
-
- /* set horz position of bars */
- GetClientRect(hwndBar, &rc);
- cx = (int)(rc.right - rc.left);
- cy = (int)(rc.bottom - rc.top);
-
- /* layout constants are defined as percentages of window width */
- rcLeft.left = cx * L_POS_START / 100;
- rcRight.left = cx * R_POS_START / 100;
- rcLeft.right = rcLeft.left + (cx * L_POS_WIDTH / 100);
- rcRight.right = rcRight.left + (cx * R_POS_WIDTH / 100);
-
- /* erase the whole marker section if requested */
- if (bErase) {
- rcLeft.top = rc.top;
- rcLeft.bottom = rc.bottom;
- rcRight.top = rc.top;
- rcRight.bottom = rc.bottom;
-
- FillRect(hdc, &rcLeft, GetStockObject(WHITE_BRUSH));
-
- FillRect(hdc, &rcRight, GetStockObject(WHITE_BRUSH));
- }
-
-
- /*
- * calculate the vertical scaling - depends on the
- * total number of lines shown
- */
-
- /* get the handles to the two lists of sections */
- view = (VIEW) SendMessage(hwndClient, TM_CURRENTVIEW, 0, 0);
- /* make sure we are in expand mode */
- if (view_isexpanded(view) == FALSE) {
- /* get rid of the dc if we made it ourselves */
- if (hdcIn == NULL) {
- ReleaseDC(hwndBar, hdc);
- }
- return;
- }
-
- item = view_getitem(view, 0);
-
- listleft = compitem_getleftsections(item);
- listright = compitem_getrightsections(item);
-
- /* if there is only one list of sections, draw nothing. The
- * picture for a single file is not very exciting.
- */
-
- if ((listleft == NULL) || (listright == NULL)) {
- /* get rid of the dc if we made it ourselves */
- if (hdcIn == NULL) {
- ReleaseDC(hwndBar, hdc);
- }
- return;
- }
-
- /* take the longest of the two files and use this
- * for vertical scaling. the scale is such that the longest file
- * *just fits*.
- */
- total_lines = line_getlinenr(section_getlastline(List_Last(listleft)));
- total_lines = max(total_lines,
- (int) line_getlinenr(section_getlastline(List_Last(listright))));
-
-
- /* get the current top row and nr of rows visible */
- toprow = SendMessage(hwndRCD, TM_TOPROW, FALSE, 0);
- endrow = SendMessage(hwndRCD, TM_ENDROW, FALSE, 0);
- endrow = min(endrow, view_getrowcount(view)-1);
-
-
-
- /*
- * find the first and last line nrs from each file currently visible.
- *
- */
- left_first = left_last = right_first = right_last = 0;
-
- for (i = toprow; i <= endrow; i++) {
- linenr = view_getlinenr_left(view, i);
-
- if (linenr > 0) {
-
- if (left_first == 0) {
- left_first = linenr;
- }
- left_first = min(left_first, linenr);
- left_last = max(left_last, linenr);
- }
-
- linenr = view_getlinenr_right(view, i);
- if (linenr > 0) {
- if (right_first == 0) {
- right_first = linenr;
- }
- right_first = min(right_first, linenr);
- right_last = max(right_last, linenr);
- }
-
- }
-
- /* draw the two markers as thick bars -> elongated rectangles */
- rcLeft.top = MulDiv(left_first-1, cy, total_lines);
- rcLeft.bottom = MulDiv(left_last, cy, total_lines);
- FillRect(hdc, &rcLeft, hbrSideBar);
-
- rcRight.top = MulDiv(right_first-1, cy, total_lines);
- rcRight.bottom = MulDiv(right_last, cy, total_lines);
- FillRect(hdc, &rcRight, hbrSideBar);
-
- /* get rid of the dc if we made it ourselves */
- if (hdcIn == NULL) {
- ReleaseDC(hwndBar, hdc);
- }
-
- }
-
-
- /***************************************************************************
- * Function: BarPaint
- *
- * Purpose:
- *
- * Paint the bar window
- */
- void
- BarPaint(HWND hwnd)
- {
- PAINTSTRUCT ps;
- HDC hdc;
- VIEW view;
- COMPITEM item;
- LIST listleft, listright;
- SECTION sec;
- int total_lines, cx, cy;
- RECT rc;
-
- hdc = BeginPaint(hwnd, &ps);
-
- /* draw a separator line at the very edge of the window */
- GetClientRect(hwnd, &rc);
- MoveToEx(hdc, (int)(rc.right-1), rc.top, NULL);
- LineTo(hdc, (int)(rc.right-1), rc.bottom);
-
-
- /* first gather information about what is to be displayed */
-
- /* find the total lines (for horz. scaling) */
-
- /* get the handles to the two lists of sections */
- view = (VIEW) SendMessage(hwndClient, TM_CURRENTVIEW, 0, 0);
-
- /* make sure we are in expand mode */
- if (view_isexpanded(view) == FALSE) {
- return;
- }
-
- item = view_getitem(view, 0);
-
- listleft = compitem_getleftsections(item);
- listright = compitem_getrightsections(item);
-
- /*
- * don't bother if there is only one list - not very interesting
- */
- if ((listleft == NULL) || (listright == NULL)) {
- EndPaint(hwnd, &ps);
- return;
- }
-
- /* take the longest of the two files and use this
- * for vertical scaling. the scale is such that the longest file
- * *just fits*.
- */
- total_lines = (int) line_getlinenr(section_getlastline(List_Last(listleft)));
- total_lines = max(total_lines,
- (int) line_getlinenr(section_getlastline(List_Last(listright))));
-
-
-
- /* horizontal spacing:
- *
- * there are two columns, for the left and right files, and a gap
- * between them criss-crossed by lines marking the links.
- *
- * Each of the columns then has three sections, for the
- * position marker, the different sections
- * and the linked sections. The width and positions of these items
- * are defined (in windiff.h) as percentages of the window width.
- */
-
- cx = (int)(rc.right - rc.left);
- cy = (int)(rc.bottom - rc.top);
-
-
- /* draw all the left sections and links */
- List_TRAVERSE(listleft, sec) {
- DrawSection(hdc, cx, cy, total_lines, sec, STATE_LEFTONLY);
-
- if (section_getlink(sec) != NULL) {
- DrawLink(hdc, cx, cy, total_lines, sec);
- }
- }
-
- /* draw all the right sections */
- List_TRAVERSE(listright, sec) {
- DrawSection(hdc, cx, cy, total_lines, sec, STATE_RIGHTONLY);
- }
-
-
-
- /* now draw current position markers */
- BarDrawPosition(hwnd, hdc, FALSE);
-
- EndPaint(hwnd, &ps);
- }
-
- /***************************************************************************
- * Function: DrawSection
- *
- * Purpose:
- *
- * Paint a single section
- */
- void
- DrawSection(HDC hdc, int cx, int cy, int lines, SECTION sec, int sidecode)
- {
- int x1, y1, x2, y2;
- HPEN hpenOld;
- HBRUSH hbrOld;
-
- /* calculate the vertical position from the scaling. the scaling
- * is such that the longest file just fits
- */
- y1 = MulDiv(line_getlinenr(section_getfirstline(sec))- 1, cy, lines);
- y2 = MulDiv(line_getlinenr(section_getlastline(sec)), cy, lines);
-
-
- /* left or right - set bar position and width*/
- if (sidecode == STATE_LEFTONLY) {
- if (section_getlink(sec) != NULL) {
- x1 = L_MATCH_START;
- x2 = L_MATCH_WIDTH;
- } else {
- x1 = L_UNMATCH_START;
- x2 = L_UNMATCH_WIDTH;
- }
- } else {
- if (section_getlink(sec) != NULL) {
- x1 = R_MATCH_START;
- x2 = R_MATCH_WIDTH;
- } else {
- x1 = R_UNMATCH_START;
- x2 = R_UNMATCH_WIDTH;
- }
- }
- /* bar position defines are in percentages of the win width (cx) */
- x1 = cx * x1 / 100;
- x2 = (cx * x2 / 100) + x1;
-
-
- /* select pens and brushes */
- if (section_getlink(sec) != NULL) {
- hpenOld = SelectObject(hdc, hpenSame);
- hbrOld = SelectObject(hdc, hbrSame);
- } else if (sidecode == STATE_LEFTONLY) {
- hpenOld = SelectObject(hdc, hpenLeft);
- hbrOld = SelectObject(hdc, hbrLeft);
- } else {
- hpenOld = SelectObject(hdc, hpenRight);
- hbrOld = SelectObject(hdc, hbrRight);
- }
-
- /* draw the section as a coloured elongated rectangle */
- Rectangle(hdc, x1, y1, x2, y2);
-
- /* de-select the pen and brush in favour of the default */
- SelectObject(hdc, hpenOld);
- SelectObject(hdc, hbrOld);
-
- }
-
- /***************************************************************************
- * Function: DrawLink
- *
- * Purpose:
- *
- * Draw a line linking two sections. Indicates a section from each
- * file that match each other. psec points to the section in the
- * left file.
- */
- void
- DrawLink(HDC hdc, int cx, int cy, int lines, SECTION sec)
- {
- int x1, y1, x2, y2;
- int ybase, yrange;
- SECTION other;
-
- other = section_getlink(sec);
-
- /* position the link line halfway down the section
- * - allow for the case where
- * the section is one line (ie halve the co-ords, not the line nr)
- */
- ybase = MulDiv(line_getlinenr(section_getfirstline(sec)) - 1, cy, lines);
- yrange = MulDiv(line_getlinenr(section_getlastline(sec)), cy, lines);
- y1 = ((yrange - ybase) / 2) + ybase;
-
- ybase = MulDiv(line_getlinenr(section_getfirstline(other)) - 1, cy, lines);
- yrange = MulDiv(line_getlinenr(section_getlastline(other)), cy, lines);
- y2 = ((yrange - ybase) / 2) + ybase;
-
- /* horizontal layout constants are defined as percentages of the
- * window width
- */
- x1 = cx * (L_MATCH_START + L_MATCH_WIDTH) / 100;
- x2 = cx * R_UNMATCH_START / 100;
-
- MoveToEx(hdc, x1, y1, NULL);
- LineTo(hdc, x2, y2);
- }
-
-
- /***************************************************************************
- * Function: BarClick
- *
- * Purpose:
- *
- * The user has clicked on the bar window. Translate the clicked position into
- * a line in one of the files if possible, and scroll the table window to
- * show that line.
- */
- void
- BarClick(HWND hwnd, int x, int y)
- {
- RECT rc;
- int xleft, xright;
- int linenr, i, this;
- BOOL bIsLeft;
- int tot_left, tot_right, total_lines;
- LIST listleft, listright;
- VIEW view;
- COMPITEM item;
- TableSelection select;
-
-
- /* find size of the window to get horz scaling, and see
- * where click was
- */
- GetClientRect(hwnd, &rc);
-
- /* was it near either of the bars ? */
-
- /* horz positioning is in percentages of window width */
- xleft = max(L_UNMATCH_START + L_UNMATCH_WIDTH,
- L_MATCH_START + L_MATCH_WIDTH);
- xright = min(R_UNMATCH_START, R_MATCH_START);
- xleft = xleft * (rc.right - rc.left) / 100;
- xright = xright * (rc.right - rc.left) / 100;
-
-
- if (x < xleft) {
- bIsLeft = TRUE;
- } else if (x > xright) {
- bIsLeft = FALSE;
- } else {
- /* click was between the two bars - ignore it */
- return;
- }
-
-
- /* calculate the vertical scaling (based on total lines displayed)
- * so that we can convert the y position into a line nr
- */
-
- /* get the handles to the two lists of sections */
- view = (VIEW) SendMessage(hwndClient, TM_CURRENTVIEW, 0, 0);
-
- /* make sure we are in expand mode */
- if (view_isexpanded(view) == FALSE) {
- return;
- }
-
- item = view_getitem(view, 0);
-
- listleft = compitem_getleftsections(item);
- listright = compitem_getrightsections(item);
-
- /* ignore the click if only one list of sections, since in
- * this case there is nothing drawn for him to click on.
- */
- if ((listleft == NULL) || (listright == NULL)) {
- return;
- }
-
- /* take the longest of the two files and use this
- * for vertical scaling. the scale is such that the longest file
- * *just fits*.
- */
- tot_left = line_getlinenr(section_getlastline(List_Last(listleft)));
- tot_right = line_getlinenr(section_getlastline(List_Last(listright)));
-
- total_lines = max(tot_left, tot_right);
-
-
- /* convert vertical position into a line nr. The vertical scaling
- * can be calculated from knowing that the longest list of
- * lines just fits in the window.
- */
- linenr = (int) (((long) total_lines * y) / (rc.bottom - rc.top)) + 1;
-
- /* check that the line is valid */
- if (bIsLeft) {
- if (linenr > tot_left) {
- return;
- }
- } else {
- if (linenr > tot_right) {
- return;
- }
- }
-
- /* search the current view, looking for a row with this
- * line nr on the correct side
- */
- for (i = 0; i < view_getrowcount(view); i++) {
- if (bIsLeft) {
- this = view_getlinenr_left(view,i);
- } else {
- this = view_getlinenr_right(view,i);
- }
-
- if (linenr == this) {
- /* found the matching line- select it in the
- * table window
- */
- select.startrow = i;
- select.startcell = 0;
- select.nrows = 1;
- select.ncells = 1;
- SendMessage(hwndRCD, TM_SELECT, 0, (long) (LPSTR)&select);
- return;
- }
- }
-
- windiff_UI(TRUE);
- MessageBox(hwndClient, LoadRcString(IDS_LINE_NOT_VISIBLE),
- "WinDiff", MB_ICONSTOP|MB_OK);
- windiff_UI(FALSE);
- }
-
-