Annotation of mstools/samples/sdktools/windiff/view.c, revision 1.1

1.1     ! root        1: 
        !             2: /******************************************************************************\
        !             3: *       This is a part of the Microsoft Source Code Samples. 
        !             4: *       Copyright (C) 1993 Microsoft Corporation.
        !             5: *       All rights reserved. 
        !             6: *       This source code is only intended as a supplement to 
        !             7: *       Microsoft Development Tools and/or WinHelp documentation.
        !             8: *       See these sources for detailed information regarding the 
        !             9: *       Microsoft samples programs.
        !            10: \******************************************************************************/
        !            11: 
        !            12: /****************************** Module Header *******************************
        !            13: * Module Name: VIEW.C
        !            14: *
        !            15: * Maps rows in window to items in COMPLIST
        !            16: *
        !            17: * Functions:
        !            18: *
        !            19: * view_new()
        !            20: * view_setcomplist()
        !            21: * view_getcomplist()
        !            22: * view_close()
        !            23: * view_delete()
        !            24: * view_outline()
        !            25: * view_expand()
        !            26: * view_gettext()
        !            27: * view_getlinenr_left()
        !            28: * view_getlinenr_right()
        !            29: * view_getwidth()
        !            30: * view_getrowcount()
        !            31: * view_getstate()
        !            32: * view_getitem()
        !            33: * view_isexpanded()
        !            34: * view_getcurrenttag()
        !            35: * view_newitem()
        !            36: * view_changeviewoptions()
        !            37: * view_changediffoptions()
        !            38: * view_findchange()
        !            39: * view_outline_opt()
        !            40: * view_freemappings()
        !            41: * view_findrow()
        !            42: * view_expand_item()
        !            43: *
        !            44: * Comments:
        !            45: *
        !            46: * A view owns a COMPLIST, and talks to a table window. The table window
        !            47: * shows 3 columns: line nr, tag and text. We also need to supply a state
        !            48: * for each row (used to select colour scheme).
        !            49: *
        !            50: * The COMPLIST can give us a list of its COMPITEMs. Each of these can give
        !            51: * us a tag (eg the filenames compared) and the text (usually the compare
        !            52: * result), and the state. We make the line number from the
        !            53: * COMPITEM's place in the list.
        !            54: *
        !            55: * If we are asked to switch to 'expand' mode, we ask the selected COMPITEM
        !            56: * for its composite section list. We can then get the state (and thus
        !            57: * the tag) from each SECTION, and the line nr and text from the LINEs within
        !            58: * each section.
        !            59: *
        !            60: * When moving between expand and outline, and when refreshing the view
        !            61: * for some option change, we have to be careful to keep the current row
        !            62: * and the selected row in the table what the user would expect.
        !            63: *
        !            64: * Functions in this module can be called from the UI thread (to refresh
        !            65: * the display) and simultaneously from a worker thread to update the
        !            66: * view mapping (view_setcomplist, view_newitem). We use a critical section
        !            67: * to manage the synchronisation. We need to protect all access/modification
        !            68: * to the view structure elements (particularly bExpand, rows, pLines and
        !            69: * pItems), BUT we must not hold the critical section over any calls
        !            70: * to SendMessage.
        !            71: *
        !            72: * We use the global options in windiff.h, and we allocate memory from the
        !            73: * heap hHeap which has been initialised elsewhere. Points in time-intensive
        !            74: * loops call Poll() defined elsewhere.
        !            75: *
        !            76: ****************************************************************************/
        !            77: 
        !            78: #include <windows.h>
        !            79: #include <stdlib.h>
        !            80: #include <commdlg.h>
        !            81: 
        !            82: #include "gutils.h"
        !            83: #include "table.h"
        !            84: #include "state.h"
        !            85: #include "windiff.h"
        !            86: #include "wdiffrc.h"
        !            87: #include "list.h"
        !            88: #include "line.h"
        !            89: #include "scandir.h"
        !            90: #include "file.h"
        !            91: #include "section.h"
        !            92: #include "compitem.h"
        !            93: #include "complist.h"
        !            94: #include "view.h"
        !            95: 
        !            96: /*
        !            97:  * data structures
        !            98:  */
        !            99: 
        !           100: /* in expand mode, we keep an array of one of these per screen line. */
        !           101: typedef struct viewline {
        !           102:         LINE line;              /* handle to LINE for this row */
        !           103:         SECTION section;        /* handle to section containing this line */
        !           104:         int nr_left;            /* line nr in left file */
        !           105:         int nr_right;           /* line nr in right file */
        !           106: } VIEWLINE, FAR * PVIEWLINE;
        !           107: 
        !           108: 
        !           109: /*
        !           110:  * The users VIEW handle is in fact a pointer to this structure
        !           111:  */
        !           112: struct view {
        !           113: 
        !           114:         HWND     hwnd;          /* the table window to send notifies to */
        !           115: 
        !           116:         COMPLIST cl;            /* the complist that we own */
        !           117: 
        !           118:    BOOL          bExpand;       /* true if we are in expand mode */
        !           119: 
        !           120:         COMPITEM ciSelect;      /* selected compitem (in expand mode) */
        !           121: 
        !           122:         int      rows;          /* number of rows in this view */
        !           123: 
        !           124:         char     nrtext[12];    /* we use this in view_gettext for the line
        !           125:                                  * number column. overwritten on each call
        !           126:                                  */
        !           127:         int      maxtag, maxrest;/* column widths in characters for cols 1, 2 */
        !           128: 
        !           129:         /* if we are in outline mode, we map the row number to one entry
        !           130:          * in this array of COMPITEM handles. this pointer will
        !           131:          * be NULL in expand mode
        !           132:          */
        !           133:         COMPITEM FAR * pItems;
        !           134: 
        !           135:         /* in expand mode we use this array of line and section handles */
        !           136:         PVIEWLINE pLines;
        !           137: };
        !           138: 
        !           139: 
        !           140: CRITICAL_SECTION CSView;
        !           141: static BOOL bDoneInit = FALSE;
        !           142: 
        !           143: #define ViewEnter()     EnterCriticalSection(&CSView);
        !           144: #define ViewLeave()     LeaveCriticalSection(&CSView);
        !           145: 
        !           146: void view_outline_opt(VIEW view, BOOL bRedraw);
        !           147: void view_freemappings(VIEW view);
        !           148: int view_findrow(VIEW view, int number, BOOL bRight);
        !           149: BOOL view_expand_item(VIEW view, COMPITEM ci);
        !           150: 
        !           151: 
        !           152: /***************************************************************************
        !           153:  * Function: view_new
        !           154:  *
        !           155:  * Purpose:
        !           156:  *
        !           157:  * Create a new view. At this point, we are told the table window handle,
        !           158:  * and nothing else.
        !           159:  *
        !           160:  */
        !           161: VIEW
        !           162: view_new(HWND hwndTable)
        !           163: {
        !           164:         VIEW view;
        !           165: 
        !           166:         if (!bDoneInit) {
        !           167:                 InitializeCriticalSection(&CSView);
        !           168:                 bDoneInit = TRUE;
        !           169:         }
        !           170: 
        !           171:         /* alloc the view from the heap */
        !           172:         view = (VIEW) gmem_get(hHeap, sizeof(struct view));
        !           173: 
        !           174:         /* set the default fields */
        !           175:         view->hwnd = hwndTable;
        !           176:         view->cl = NULL;
        !           177:         view->bExpand = FALSE;
        !           178:         view->ciSelect = NULL;
        !           179:         view->rows = 0;
        !           180:         view->pItems = NULL;
        !           181:         view->pLines = NULL;
        !           182: 
        !           183:         return(view);
        !           184: }
        !           185: 
        !           186: 
        !           187: /***************************************************************************
        !           188:  * Function: view_setcomplist
        !           189:  *
        !           190:  * Purpose:
        !           191:  *
        !           192:  * We have to separate view_new and view_setcomplist because we need
        !           193:  * to give the view handle to the complist and the complist handle to the
        !           194:  * view. So do a view_new to create a null view; then complist_new() to
        !           195:  * which you pass a view handle. The complist will then register itself
        !           196:  * with the view by calling this function. During the build of the complist,
        !           197:  * it will also update us by calling view_additem, so that we can refresh
        !           198:  * the display.
        !           199:  *
        !           200:  * Here we should initialise an outline view of the complist.
        !           201:  *
        !           202:  * We also talk to the status bar using SetNames to set the names of
        !           203:  * the two items.
        !           204:  */
        !           205: BOOL
        !           206: view_setcomplist(VIEW view, COMPLIST cl)
        !           207: {
        !           208:         LPSTR left, right, both;
        !           209: 
        !           210:         if (view == NULL) {
        !           211:                 return(FALSE);
        !           212:         }
        !           213: 
        !           214:         /* there can be only one call to this per VIEW */
        !           215:         if (view->cl != NULL) {
        !           216:                 return (FALSE);
        !           217:         }
        !           218: 
        !           219:         ViewEnter();
        !           220: 
        !           221:         view->cl = cl;
        !           222: 
        !           223:         /* set names on status bar to root names of left and right trees */
        !           224:         left = complist_getroot_left(cl);
        !           225:         right = complist_getroot_right(cl);
        !           226:         both = gmem_get(hHeap, lstrlen(left) + lstrlen(right) +4);
        !           227:         wsprintf((LPTSTR)both, "%s : %s", left, right);
        !           228:         ViewLeave();   
        !           229:         SetNames(both);
        !           230:         ViewEnter();   
        !           231:         gmem_free(hHeap, both, lstrlen(both)+1);
        !           232:         complist_freeroot_left(cl, left);
        !           233:         complist_freeroot_right(cl, right);
        !           234: 
        !           235:         ViewLeave();
        !           236: 
        !           237:         view_outline(view);
        !           238: }
        !           239: 
        !           240: 
        !           241: /***************************************************************************
        !           242:  * Function: view_getcomplist
        !           243:  *
        !           244:  * Purpose:
        !           245:  *
        !           246:  * Return a handle to the complist owned by this view
        !           247:  */
        !           248: COMPLIST
        !           249: view_getcomplist(VIEW view)
        !           250: {
        !           251:         if (view == NULL) {
        !           252:                 return(NULL);
        !           253:         }
        !           254: 
        !           255:         return(view->cl);
        !           256: }
        !           257: 
        !           258: 
        !           259: /***************************************************************************
        !           260:  * Function: view_close
        !           261:  *
        !           262:  * Purpose:
        !           263:  *
        !           264:  * Close a view. Notify the table window that this view should be
        !           265:  * closed. When the table window has finished with it, it will send
        !           266:  * a TQ_CLOSE notify that should result in view_delete being called
        !           267:  * and the memory being freed.
        !           268:  */
        !           269: void
        !           270: view_close(VIEW view)
        !           271: {
        !           272:         if (view == NULL) {
        !           273:                 return;
        !           274:         }
        !           275: 
        !           276:         SendMessage(view->hwnd, TM_NEWID, 0, 0);
        !           277: }
        !           278: 
        !           279: 
        !           280: /***************************************************************************
        !           281:  * Function: view_delete
        !           282:  *
        !           283:  * Purpose:
        !           284:  *
        !           285:  * Delete a view and all associated data.
        !           286:  *
        !           287:  * This function should only be called in response to the table window
        !           288:  * sending a TQ_CLOSE message. To close the view, call view_close and
        !           289:  * wait for the TQ_CLOSE before calling this.
        !           290:  *
        !           291:  * We delete the associated COMPLIST and all its associated structures.
        !           292:  */
        !           293: void
        !           294: view_delete(VIEW view)
        !           295: {
        !           296:         if (view == NULL) {
        !           297:                 return;
        !           298:         }
        !           299: 
        !           300:         /* we have two arrays that are used for the mapping - an array
        !           301:          * of compitem handles in outline mode, and an array of
        !           302:          * VIEWLINE structures in expand mode
        !           303:          */
        !           304: 
        !           305:         view_freemappings(view);
        !           306: 
        !           307:         complist_delete(view->cl);
        !           308: 
        !           309:         gmem_free(hHeap, (LPSTR) view, sizeof(struct view));
        !           310: }
        !           311: 
        !           312: 
        !           313: /***************************************************************************
        !           314:  * Function: view_outline
        !           315:  *
        !           316:  * Purpose:
        !           317:  *
        !           318:  * Build an outline mode mapping where one row represents one COMPITEM in
        !           319:  * the list. Check the global option flag outline_include to see which items
        !           320:  * we should include.
        !           321:  *
        !           322:  * If we were in expand mode, then set as the selection the row in outline mode
        !           323:  * that we were expanding. Also remember to free up the expand mode mapping
        !           324:  * array
        !           325:  *
        !           326:  * Once we have built the new mapping, notify the table window to
        !           327:  * redraw itself.
        !           328:  */
        !           329: void
        !           330: view_outline(VIEW view)
        !           331: {
        !           332:         if (view == NULL) {
        !           333:                 return;
        !           334:         }
        !           335: 
        !           336:         /* all work done by view_outline_opt - this function
        !           337:          * gives us the option of not updating the display
        !           338:          */
        !           339:         view_outline_opt(view, TRUE);
        !           340: }
        !           341: 
        !           342: 
        !           343: 
        !           344: /***************************************************************************
        !           345:  * Function: view_expand
        !           346:  *
        !           347:  * Purpose:
        !           348:  *
        !           349:  * Switch to expand mode, expanding the given row into a view
        !           350:  * of the differences in that file.
        !           351:  *
        !           352:  * Map the given row nr into a compitem handle, and then
        !           353:  * call the internal function with that.
        !           354:  */
        !           355: BOOL    
        !           356: view_expand(VIEW view, long row)
        !           357: {
        !           358:         COMPITEM ci;
        !           359:         BOOL bRet;
        !           360: 
        !           361:         ViewEnter();
        !           362: 
        !           363:         if ((view == NULL) || (view->bExpand)) {
        !           364:                 /* no view, or already expanded */
        !           365:                 ViewLeave();
        !           366:                 return(FALSE);
        !           367:         }
        !           368: 
        !           369:         if (row >= view->rows) {
        !           370:                 /* no such row */
        !           371:                 ViewLeave();
        !           372:                 return FALSE;
        !           373:         }
        !           374: 
        !           375:         /* remember the compitem we are expanding */
        !           376:         ci = view->pItems[row];
        !           377: 
        !           378:         bRet = view_expand_item(view, ci);
        !           379:         // view_expand_item does the...
        !           380:         // ViewLeave();
        !           381:         return(bRet);
        !           382: }
        !           383: 
        !           384: 
        !           385: /***************************************************************************
        !           386:  * Function: view_gettext
        !           387:  *
        !           388:  * Purpose:
        !           389:  *
        !           390:  * Return the text associated with a given column of a given row.
        !           391:  * Return a pointer that does not need to be freed after use - ie
        !           392:  * a pointer into our data somewhere, not a copy
        !           393:  */
        !           394: LPSTR
        !           395: view_gettext(VIEW view, long row, int col)
        !           396: {
        !           397:         int line;
        !           398:         int state;
        !           399:         LPSTR pstr;
        !           400: 
        !           401: 
        !           402:         if (view == NULL) {
        !           403:                 return (NULL);
        !           404:         }
        !           405: 
        !           406:         ViewEnter();
        !           407: 
        !           408:         if (row >= view->rows) {
        !           409:                 ViewLeave();
        !           410:                 return(NULL);
        !           411:         }
        !           412: 
        !           413:         if (view->bExpand) {
        !           414:                 /* we are in expand mode */
        !           415:                 
        !           416:                 state = section_getstate(view->pLines[row].section);
        !           417: 
        !           418:                 switch(col) {
        !           419:                 case 0:
        !           420:                         /* row nr */
        !           421:                                                 
        !           422:                         /* line numbers can be from either original file
        !           423:                          * this is a menu-selectable option
        !           424:                          */
        !           425:                         switch(line_numbers) {
        !           426:                         case IDM_NONRS:
        !           427:                                 pstr = NULL;
        !           428:                                 break;
        !           429: 
        !           430:                         case IDM_LNRS:
        !           431:                                 line = view->pLines[row].nr_left;
        !           432:                                 if (state == STATE_MOVEDRIGHT) {
        !           433:                                         line = -line;
        !           434:                                 }
        !           435:                                 break;
        !           436: 
        !           437:                         case IDM_RNRS:
        !           438:                                 line = view->pLines[row].nr_right;
        !           439:                                 if (state == STATE_MOVEDLEFT) {
        !           440:                                         line = -line;
        !           441:                                 }
        !           442:                                 break;
        !           443:                         }
        !           444:                         if (line == 0) {
        !           445:                                 ViewLeave();
        !           446:                                 return(NULL);
        !           447:                         }
        !           448: 
        !           449:                         if (line < 0) {
        !           450:                                 /* lines that are moved appear twice.
        !           451:                                  * show the correct-sequence line nr
        !           452:                                  * for the out-of-seq. copy in brackets.
        !           453:                                  */
        !           454:                                 wsprintf((LPTSTR)view->nrtext, "(%d)", abs(line));
        !           455:                         } else  {
        !           456:                                 wsprintf((LPTSTR)view->nrtext, "%d", line);
        !           457:                         }
        !           458:                         pstr = view->nrtext;
        !           459:                         break;
        !           460: 
        !           461:                 case 1:
        !           462:                         /* tag text - represents the state of the line */
        !           463: 
        !           464: 
        !           465:                         switch(state) {
        !           466:                         case STATE_SAME:
        !           467:                                 pstr = "    ";
        !           468:                                 break;
        !           469: 
        !           470:                         case STATE_LEFTONLY:
        !           471:                                 pstr = " <! ";
        !           472:                                 break;
        !           473: 
        !           474:                         case STATE_RIGHTONLY:
        !           475:                                 pstr = " !> ";
        !           476:                                 break;
        !           477: 
        !           478:                         case STATE_MOVEDLEFT:
        !           479:                                 pstr = " <- ";
        !           480:                                 break;
        !           481: 
        !           482:                         case STATE_MOVEDRIGHT:
        !           483:                                 pstr = " -> ";
        !           484:                                 break;
        !           485:                         }
        !           486:                         break;
        !           487: 
        !           488:                 case 2:
        !           489:                         /* main text - line */
        !           490:                         pstr = line_gettext(view->pLines[row].line);
        !           491:                         break;
        !           492:                 }
        !           493:         } else {
        !           494:                 /* outline mode */
        !           495:                 switch(col) {
        !           496:                 case 0:
        !           497:                         /* row number - just the line number */
        !           498:                         wsprintf((LPTSTR)view->nrtext, "%d", row+1);
        !           499:                         pstr = view->nrtext;
        !           500:                         break;
        !           501: 
        !           502:                 case 1:
        !           503:                         /* tag */
        !           504:                         pstr = compitem_gettext_tag(view->pItems[row]);
        !           505:                         break;
        !           506: 
        !           507:                 case 2:
        !           508:                         /* result text */
        !           509:                         pstr = compitem_gettext_result(view->pItems[row]);
        !           510:                         break;
        !           511:                 }
        !           512:         }
        !           513:         ViewLeave();
        !           514:         return(pstr);
        !           515: }
        !           516: 
        !           517: /***************************************************************************
        !           518:  * Function: view_getlinenr_left
        !           519:  *
        !           520:  * Purpose:
        !           521:  *
        !           522:  * Return the line number that this row had in the original left
        !           523:  * file. 0 if not in expand mode. 0 if this row was not in the left file.
        !           524:  * -(linenr) if this row is a MOVED line, and this is the right file
        !           525:  * copy
        !           526:  */
        !           527: int
        !           528: view_getlinenr_left(VIEW view, long row)
        !           529: {
        !           530:         int state, line;
        !           531: 
        !           532:         if ((view == NULL) || (row >= view->rows) || !view->bExpand) {
        !           533:                 return 0;
        !           534:         }
        !           535: 
        !           536:         ViewEnter();
        !           537:         state = section_getstate(view->pLines[row].section);
        !           538:         line = view->pLines[row].nr_left;
        !           539:         if (state == STATE_MOVEDRIGHT) {
        !           540:                 line = -line;
        !           541:         }
        !           542:         ViewLeave();
        !           543: 
        !           544:         return(line);
        !           545: }
        !           546: 
        !           547: /***************************************************************************
        !           548:  * Function: view_getlinenr_right
        !           549:  *
        !           550:  * Purpose:
        !           551:  *
        !           552:  * Return the line number that this row had in the original right
        !           553:  * file. 0 if not in expand mode. 0 if this row was not in the right file.
        !           554:  * -(linenr) if this row is a MOVED line, and this is the left file
        !           555:  * copy
        !           556:  */
        !           557: int
        !           558: view_getlinenr_right(VIEW view, long row)
        !           559: {
        !           560:         int state, line;
        !           561: 
        !           562:         if ((view == NULL) || (row > view->rows) || !view->bExpand) {
        !           563:                 return 0;
        !           564:         }
        !           565: 
        !           566:         ViewEnter();
        !           567: 
        !           568:         state = section_getstate(view->pLines[row].section);
        !           569:         line = view->pLines[row].nr_right;
        !           570:         if (state == STATE_MOVEDLEFT) {
        !           571:                 line = -line;
        !           572:         }
        !           573:         ViewLeave();
        !           574: 
        !           575:         return(line);
        !           576: }
        !           577: 
        !           578: 
        !           579: /***************************************************************************
        !           580:  * Function: view_getwidth
        !           581:  *
        !           582:  * Purpose:
        !           583:  *
        !           584:  * Find the maximum width in characters for the given column 
        !           585:  */
        !           586: int
        !           587: view_getwidth(VIEW view, int col)
        !           588: {
        !           589:         if (view == NULL) {
        !           590:                 return(0);
        !           591:         }
        !           592: 
        !           593:         switch(col) {
        !           594:         case 0:
        !           595:                 /* line nr column - always 5 characters wide */
        !           596:                 return(5);
        !           597: 
        !           598:         case 1:
        !           599:                 /* this is a proportional font field, so add on a margin
        !           600:                  * for error
        !           601:                  */
        !           602:                 return(view->maxtag + (view->maxtag / 20));
        !           603:         case 2:
        !           604:                 /* this now includes the tab expansion allowance */
        !           605:                 return(view->maxrest);
        !           606:         default:
        !           607:                 return(0);
        !           608:         }
        !           609: }
        !           610: 
        !           611: /***************************************************************************
        !           612:  * Function: view_getrowcount
        !           613:  *
        !           614:  * Purpose:
        !           615:  *
        !           616:  * How many rows are there in this view ? 
        !           617:  */
        !           618: long
        !           619: view_getrowcount(VIEW view)
        !           620: {
        !           621:         if (view == NULL) {
        !           622:                 return(0);
        !           623:         }
        !           624: 
        !           625:         return(view->rows);
        !           626: }
        !           627: 
        !           628: /***************************************************************************
        !           629:  * Function: view_getstate
        !           630:  *
        !           631:  * Purpose:
        !           632:  *
        !           633:  * Return the state for the current row. This is used
        !           634:  * to select the text colour for the row
        !           635:  *
        !           636:  * States for sections are obtained from section_getstate (and apply, and
        !           637:  * to all lines in that section. States for compitems are obtained
        !           638:  * from compitem_getstate.
        !           639:  */
        !           640: int
        !           641: view_getstate(VIEW view, long row)
        !           642: {
        !           643:         int state;
        !           644: 
        !           645:         if (view == NULL) {
        !           646:                 return(0);
        !           647:         }
        !           648: 
        !           649:         ViewEnter();
        !           650:         if (row >= view->rows) {
        !           651:                 state = 0;
        !           652:         } else if (view->bExpand) {
        !           653:                 /* its a line state that's needed */
        !           654:                 state = section_getstate(view->pLines[row].section);
        !           655:         } else {
        !           656: 
        !           657:                 /* its a compitem state */
        !           658:                 state = compitem_getstate(view->pItems[row]);
        !           659:         }
        !           660:         ViewLeave();
        !           661:         return(state);
        !           662: }
        !           663: 
        !           664: /***************************************************************************
        !           665:  * Function: view_gethandle
        !           666:  *
        !           667:  * Purpose:
        !           668:  *
        !           669:  * Return a handle to the current compitem. In expand mode,
        !           670:  * returns the handle to the compitem we are expanding. In outline
        !           671:  * mode, returns the handle to the compitem for the given row, if valid,
        !           672:  * or NULL otherwise. row is only used if not in expand mode.
        !           673:  */
        !           674: COMPITEM
        !           675: view_getitem(VIEW view, long row)
        !           676: {
        !           677:         COMPITEM ci;
        !           678: 
        !           679:         if (view == NULL) {
        !           680:                 return(NULL);
        !           681:         }
        !           682: 
        !           683:         ViewEnter();
        !           684: 
        !           685:         if (!view->bExpand) {
        !           686:                 if ((row >= 0) && (row < view->rows)) {
        !           687:                         ci = view->pItems[row];
        !           688:                 } else {
        !           689:                         ci = NULL;
        !           690:                 }
        !           691:         } else {
        !           692:                 ci = view->ciSelect;
        !           693:         }
        !           694: 
        !           695:         ViewLeave();
        !           696:         return(ci);
        !           697: }
        !           698: 
        !           699: /***************************************************************************
        !           700:  * Function: view_isexpanded
        !           701:  *
        !           702:  * Purpose:
        !           703:  *
        !           704:  * Return TRUE if the current mapping is expanded mode
        !           705:  */
        !           706: BOOL
        !           707: view_isexpanded(VIEW view)      
        !           708: {
        !           709:         if (view == NULL) {
        !           710:                 return(FALSE);
        !           711:         }
        !           712:         return(view->bExpand);
        !           713: }
        !           714: 
        !           715: 
        !           716: /***************************************************************************
        !           717:  * Function: view_getcurrenttag
        !           718:  *
        !           719:  * Purpose:
        !           720:  *
        !           721:  * Return a text string describing the view. This is NULL in outline mode,
        !           722:  * or the tag text for the current compitem in expanded mode
        !           723:  */
        !           724: LPSTR
        !           725: view_getcurrenttag(VIEW view)
        !           726: {
        !           727:         LPSTR str;
        !           728: 
        !           729:         if ((view == NULL) || (!view->bExpand)) {
        !           730:                 return(NULL);
        !           731:         } else {
        !           732:                 ViewEnter();
        !           733: 
        !           734:                 str = compitem_gettext_tag(view->ciSelect);
        !           735: 
        !           736:                 ViewLeave();
        !           737:                 return(str);
        !           738: 
        !           739:         }
        !           740: }
        !           741: 
        !           742: 
        !           743: /***************************************************************************
        !           744:  * Function: view_newitem
        !           745:  *
        !           746:  * Purpose:
        !           747:  *
        !           748:  * Notify that CompItems have been added to the complist.
        !           749:  *
        !           750:  * Rebuild the view (if in outline mode), and refresh the table. Use
        !           751:  * the table message TM_APPEND if possible (if column widths have not
        !           752:  * change). If we have to do TM_NEWLAYOUT, then ensure we scroll
        !           753:  * back to the right row afterwards.
        !           754:  *
        !           755:  * This causes a Poll() to take place. We return TRUE if an abort is
        !           756:  * pending - in this case, the caller should abandon the scan loop.
        !           757:  *
        !           758:  * Enter the critical section for this function since this can be
        !           759:  * called from the worker thread while the UI thread is using the
        !           760:  * view that we are about to change.
        !           761:  *
        !           762:  * EXCEPT THAT WE DON'T DARE.  We cannot ever call SendMessage from the
        !           763:  * worker thread within CSView.  If there is conflict, it will hang.
        !           764:  */
        !           765: BOOL
        !           766: view_newitem(VIEW view)
        !           767: {
        !           768:         int maxtag, maxrest;
        !           769:         long rownr;
        !           770: 
        !           771:         if ((view == NULL) || (view->bExpand)) {
        !           772:                 /* not in outline mode - nothing to do */
        !           773:                 return(Poll());
        !           774:         }
        !           775: 
        !           776:         /* save some state about the present mapping */
        !           777:         maxtag = view->maxtag;
        !           778:         maxrest = view->maxrest;
        !           779: 
        !           780:         /* re-do the outline mapping, but don't tell the table
        !           781:          * class.
        !           782:          */
        !           783:         view_outline_opt(view, FALSE);
        !           784: 
        !           785:         /* have the column widths changed ? */
        !           786:         if ((maxtag < view->maxtag) || (maxrest < view->maxrest)) {
        !           787:                 /* yes - need complete redraw */
        !           788: 
        !           789:                 /* find the row at the top of the window */
        !           790:                 rownr = SendMessage(view->hwnd, TM_TOPROW, FALSE, 0);
        !           791: 
        !           792:                 /* switch to new mapping */
        !           793:                 SendMessage(view->hwnd, TM_NEWLAYOUT, 0, (DWORD) view);
        !           794: 
        !           795:                 /* return to old row if possible - we know
        !           796:                  * that row is still there since we have only added
        !           797:                  * rows, and not changed any of the existing mapping
        !           798:                  *
        !           799:                  * Alas this is no longer true.  However the table class
        !           800:                  * will defend itself against calls for a bogus top row.
        !           801:                  */
        !           802:                 if (rownr >= 0) {
        !           803:                         SendMessage(view->hwnd, TM_TOPROW, TRUE, rownr);
        !           804:                 }
        !           805:         } else {
        !           806:                 /* no - we can just append */
        !           807: 
        !           808:                 /*
        !           809:                  * The mapping may have
        !           810:                  * changed since we released the critsec. however we are still
        !           811:                  * safe. The table will not allow us to reduce the number of
        !           812:                  * rows, so the worst that can happen is that the table will
        !           813:                  * think there are too many rows, and the table message handler
        !           814:                  * will handle this correctly (return null for the text).
        !           815:                  * The only visible effect is therefore that the scrollbar
        !           816:                  * position is wrong.
        !           817:                  */
        !           818: 
        !           819:                 SendMessage(view->hwnd, TM_APPEND, view->rows, (DWORD) view);
        !           820:         }
        !           821: 
        !           822: 
        !           823:         /* Poll to keep the UI updated on NT. Returns true if abort pending.
        !           824:          */
        !           825:         return(Poll());
        !           826: }
        !           827: 
        !           828: /***************************************************************************
        !           829:  * Function: view_changeviewoptions
        !           830:  *
        !           831:  * Purpose:
        !           832:  *
        !           833:  * The view mapping options (eg outline_include, expand_mode) have changed -
        !           834:  * re-do the mapping and then scroll back to the same position in the window
        !           835:  * if possible.
        !           836:  */
        !           837: void
        !           838: view_changeviewoptions(VIEW view)
        !           839: {
        !           840:         long row;
        !           841:         int state, number;
        !           842:         BOOL bRight;
        !           843: 
        !           844:         if (view == NULL) {
        !           845:                 return;
        !           846:         }
        !           847: 
        !           848:         /* find what row we are currently on. Do this BEFORE we enter CSView */
        !           849:         row = SendMessage(view->hwnd, TM_TOPROW, FALSE, 0);
        !           850: 
        !           851:         ViewEnter();
        !           852: 
        !           853:         if (!view->bExpand) {
        !           854: 
        !           855:                 /* outline mode. maintaining current position is
        !           856:                  * unimportant
        !           857:                  */
        !           858:                 view_outline(view);
        !           859:                 ViewLeave();
        !           860:                 return;
        !           861:         }
        !           862: 
        !           863:         /* expanded mode */
        !           864:         
        !           865: 
        !           866:         /* save the line number on one side (and remember which side) */
        !           867:         if (row >= view->rows) {
        !           868:                 number = -1;
        !           869:         } else {
        !           870:                 state = section_getstate(view->pLines[row].section);
        !           871:                 if ((state == STATE_MOVEDRIGHT) ||
        !           872:                     (state == STATE_RIGHTONLY)) {
        !           873:                             bRight = TRUE;
        !           874:                             number = view->pLines[row].nr_right;
        !           875:                 } else {
        !           876:                         bRight = FALSE;
        !           877:                         number = view->pLines[row].nr_left;
        !           878:                 }
        !           879:         }
        !           880: 
        !           881:         /* make the new mapping */
        !           882:         view_expand_item(view, view->ciSelect);
        !           883: 
        !           884:         /* find the nearest row in the new view */
        !           885:         if (number >= 0) {
        !           886: 
        !           887:                 ViewEnter();
        !           888:                 row = view_findrow(view, number, bRight);
        !           889:                 ViewLeave();
        !           890:         
        !           891:                 /* scroll this row to top of window */
        !           892:                 if (row >= 0) {
        !           893: 
        !           894:                         SendMessage(view->hwnd, TM_TOPROW, TRUE, row);
        !           895:                         return;
        !           896:                 }
        !           897:         }
        !           898: }
        !           899: 
        !           900: /***************************************************************************
        !           901:  * Function: view_changediffoptions
        !           902:  *
        !           903:  * Purpose:
        !           904:  *
        !           905:  * The compare options have changed - re-do the compare completely
        !           906:  * and make the new mapping. Retain current position in the file.
        !           907:  */
        !           908: void
        !           909: view_changediffoptions(VIEW view)
        !           910: {
        !           911:         int state, number;
        !           912:         long row;
        !           913:         BOOL bRight;
        !           914:         LIST li;
        !           915:         COMPITEM ci;
        !           916: 
        !           917:         if (view == NULL) {
        !           918:                 return;
        !           919:         }
        !           920: 
        !           921:         /*
        !           922:          * get current row before entering critsec.
        !           923:          */
        !           924:         row = SendMessage(view->hwnd, TM_TOPROW, FALSE, 0);
        !           925: 
        !           926:         ViewEnter();
        !           927: 
        !           928:         /* find the current line number so we can go back to it
        !           929:          * (only if we are in expanded mode
        !           930:          */
        !           931:         if (view->bExpand) {
        !           932: 
        !           933:                 state = section_getstate(view->pLines[row].section);
        !           934:                 if ((state == STATE_MOVEDRIGHT) ||
        !           935:                     (state == STATE_RIGHTONLY)) {
        !           936:                             bRight = TRUE;
        !           937:                             number = view->pLines[row].nr_right;
        !           938:                 } else {
        !           939:                         bRight = FALSE;
        !           940:                         number = view->pLines[row].nr_left;
        !           941:                 }
        !           942:         }
        !           943: 
        !           944:         /* To force a recompare using the new options, we must
        !           945:          * tell each compitem to discard its current compare result.
        !           946:          * We need to traverse the list of compitems calling this
        !           947:          * for each compare.
        !           948:          */
        !           949:         li = complist_getitems(view->cl);
        !           950: 
        !           951:         for (ci = (COMPITEM) List_First(li); ci != NULL; ci = (COMPITEM) List_Next(ci)) {
        !           952:                 compitem_discardsections(ci);
        !           953:         }
        !           954: 
        !           955:         /* if we are in outline mode, we have nothing more to do */
        !           956:         if (!view->bExpand) {
        !           957:                 ViewLeave();
        !           958:                 return;
        !           959:         }
        !           960: 
        !           961:         view_expand_item(view, view->ciSelect);
        !           962: 
        !           963:         /* find the nearest row in the new view */
        !           964:         ViewEnter();
        !           965:         row = view_findrow(view, number, bRight);
        !           966:         ViewLeave();
        !           967: 
        !           968:         /* scroll this row to top of window */
        !           969:         if (row >= 0) {
        !           970:                 SendMessage(view->hwnd, TM_TOPROW, TRUE, row);
        !           971:         }
        !           972: }
        !           973: 
        !           974: 
        !           975: /***************************************************************************
        !           976:  * Function: view_findchange
        !           977:  *
        !           978:  * Purpose:
        !           979:  *
        !           980:  * Find the next changed - ie non-same - row in a given direction.
        !           981:  * For outline mode we find the next STATE_DIFFER. For expand mode, we
        !           982:  * find the next section
        !           983:  */
        !           984: long
        !           985: view_findchange(VIEW view, long startrow, BOOL bForward)
        !           986: {
        !           987:         long i;
        !           988: 
        !           989:         if (view == NULL) {
        !           990:                 return(0);
        !           991:         }
        !           992: 
        !           993:         ViewEnter();
        !           994: 
        !           995:         if (bForward) {
        !           996: 
        !           997:                 if (startrow >= view->rows) {
        !           998:                         ViewLeave();
        !           999:                         return(-1);
        !          1000:                 }
        !          1001: 
        !          1002:                 if (!view->bExpand) {
        !          1003: 
        !          1004:                         /* look for next compitem with an expandable state*/
        !          1005:                         for (i = startrow; i < view->rows; i++) {
        !          1006:                                 if (compitem_getstate(view->pItems[i]) == STATE_DIFFER) {
        !          1007:                                         ViewLeave();
        !          1008:                                         return(i);
        !          1009:                                 }
        !          1010:                         }
        !          1011:                         /* none found */
        !          1012:                         ViewLeave();
        !          1013:                         return(-1);
        !          1014:                 } else {
        !          1015:                         /*
        !          1016:                          * find the next line that matches, then go on to the
        !          1017:                          * next line that does not match
        !          1018:                          *
        !          1019:                          */
        !          1020:                         for (i= startrow; i < view->rows; i++) {
        !          1021:                                 if (section_getstate(view->pLines[i].section)
        !          1022:                                         == STATE_SAME) {
        !          1023:                                                 break;
        !          1024:                                 }
        !          1025:                         }
        !          1026:                         for ( ; i < view->rows; i++) {
        !          1027:                                 if (section_getstate(view->pLines[i].section)
        !          1028:                                         != STATE_SAME) {
        !          1029:                                                 ViewLeave();
        !          1030:                                                 return(i);
        !          1031:                                 }
        !          1032:                         }
        !          1033: 
        !          1034:                         ViewLeave();
        !          1035: 
        !          1036:                         return(-1);
        !          1037:                 }
        !          1038:         } else {
        !          1039:                 /* same search backwards */
        !          1040:                 if (startrow <= 0) {
        !          1041:                         ViewLeave();
        !          1042:                         return(-1);
        !          1043:                 }
        !          1044:                 if (view->bExpand) {
        !          1045:                         /* search backwards for first row that is not
        !          1046:                          * changed (has state SAME). then carry on for
        !          1047:                          * the next changed row.
        !          1048:                          */
        !          1049:                         for (i = startrow; i >= 0; i--) {
        !          1050:                                 if (section_getstate(view->pLines[i].section)
        !          1051:                                         == STATE_SAME) {
        !          1052:                                                 break;
        !          1053:                                 }
        !          1054:                         }
        !          1055:                         for ( ; i >= 0; i--) {
        !          1056:                                 if (section_getstate(view->pLines[i].section)
        !          1057:                                         != STATE_SAME) {
        !          1058:                                                 ViewLeave();
        !          1059:                                                 return(i);
        !          1060:                                 }
        !          1061:                         }
        !          1062:                         ViewLeave();
        !          1063:                         return(-1);
        !          1064:                 } else {
        !          1065:                         for (i = startrow; i >= 0; i--) {
        !          1066:                                 if(compitem_getstate(view->pItems[i]) == STATE_DIFFER) {
        !          1067:                                         ViewLeave();
        !          1068:                                         return(i);
        !          1069:                                 }
        !          1070:                         }
        !          1071:                         ViewLeave();
        !          1072:                         return(-1);
        !          1073:                 }
        !          1074:         }
        !          1075: }
        !          1076: 
        !          1077: 
        !          1078: 
        !          1079: /***************************************************************************
        !          1080:  * Function: view_findrow
        !          1081:  *
        !          1082:  * Purpose:
        !          1083:  *
        !          1084:  * Find the new row number for the line numbered 'number'
        !          1085:  * or the nearest line if possible. If bRight is true, number is
        !          1086:  * a right file number; otherwise it is a left file number.
        !          1087:  *
        !          1088:  * We must be in expand mode
        !          1089:  */
        !          1090: int     
        !          1091: view_findrow(VIEW view, int number, BOOL bRight)
        !          1092: {
        !          1093:         int i;
        !          1094: 
        !          1095:         if (!view->bExpand) {   
        !          1096:                 return(0);
        !          1097:         }
        !          1098: 
        !          1099:         for (i = 0; i < view->rows; i++) {
        !          1100: 
        !          1101:                 if (bRight) {
        !          1102:                         if (view->pLines[i].nr_right == number) {
        !          1103: 
        !          1104:                                 /* found the exact number */
        !          1105:                                 return(i);
        !          1106: 
        !          1107:                         } else if (view->pLines[i].nr_right > number) {
        !          1108: 
        !          1109:                                 /* passed our line -stop here */
        !          1110:                                 return(i);
        !          1111:                         }
        !          1112:                 } else {
        !          1113:                         if (view->pLines[i].nr_left == number) {
        !          1114: 
        !          1115:                                 /* found the exact number */
        !          1116:                                 return(i);
        !          1117: 
        !          1118:                         } else if (view->pLines[i].nr_left > number) {
        !          1119: 
        !          1120:                                 /* passed our line -stop here */
        !          1121:                                 return(i);
        !          1122:                         }
        !          1123:                 }
        !          1124:         }
        !          1125:         return(-1);
        !          1126: }
        !          1127: 
        !          1128: /***************************************************************************
        !          1129:  * Function: view_freemappings
        !          1130:  *
        !          1131:  * Purpose:
        !          1132:  *
        !          1133:  * Free memory associated with the expand mode or outline mode mappings
        !          1134:  * called whenever we rebuild the mapping, and on deletion
        !          1135:  */
        !          1136: void
        !          1137: view_freemappings(VIEW view)
        !          1138: {
        !          1139: 
        !          1140:         if (view->pLines) {
        !          1141:                 gmem_free(hHeap, (LPSTR) view->pLines,
        !          1142:                         view->rows * sizeof(VIEWLINE));
        !          1143:                 view->pLines = NULL;
        !          1144:         } else if (view->pItems) {
        !          1145: 
        !          1146:                 /* previous outline mapping array is still there - free it
        !          1147:                  * before we build a new one
        !          1148:                  */
        !          1149: 
        !          1150:                 gmem_free(hHeap, (LPSTR) view->pItems,
        !          1151:                         view->rows * sizeof(COMPLIST));
        !          1152:                 view->pItems = NULL;
        !          1153:         }
        !          1154: }
        !          1155: 
        !          1156: /***************************************************************************
        !          1157:  * Function: view_outline_opt
        !          1158:  *
        !          1159:  * Purpose:
        !          1160:  *
        !          1161:  * Build a view outline to map one row to a COMPITEM handle by traversing
        !          1162:  * the list of COMPITEMs obtained from our complist.
        !          1163:  * Optionally tell the table class to redraw (if bRedraw), and if so,
        !          1164:  * scroll the new table to select the row that represents the
        !          1165:  * file we were expanding, if possible
        !          1166:  */
        !          1167: void
        !          1168: view_outline_opt(VIEW view, BOOL bRedraw)
        !          1169: {
        !          1170:         int prev_row = -1;      /* the row nr of the previously-expanded row*/
        !          1171:         int i;                  /* nr of includable items */
        !          1172:         LIST li;
        !          1173:         COMPITEM ci;
        !          1174:         int state;
        !          1175:         TableSelection select;
        !          1176: 
        !          1177:         /*
        !          1178:          * check that view_setcomplist has already been called. if not,
        !          1179:          * nothing to do
        !          1180:          */
        !          1181:         if (view->cl == NULL) {
        !          1182:                 return;
        !          1183:         }
        !          1184: 
        !          1185:         ViewEnter();
        !          1186: 
        !          1187:         /* clear the mode flag and free up memory associated with expand mode */
        !          1188:         view->bExpand = FALSE;
        !          1189:         view_freemappings(view);
        !          1190: 
        !          1191:         /* traverse the list of compitems counting up the number of
        !          1192:          * includable items
        !          1193:          */
        !          1194:         li = complist_getitems(view->cl);
        !          1195: 
        !          1196:         ci = (COMPITEM) List_First(li);
        !          1197:         for (i = 0; ci != NULL; ci = (COMPITEM) List_Next(ci)) {
        !          1198: 
        !          1199:                 state = compitem_getstate(ci);
        !          1200: 
        !          1201:                 if (((outline_include & INCLUDE_SAME) && (state == STATE_SAME)) ||
        !          1202:                     ((outline_include & INCLUDE_DIFFER) && (state == STATE_DIFFER)) ||
        !          1203:                     ((outline_include & INCLUDE_LEFTONLY) && (state == STATE_FILELEFTONLY)) ||
        !          1204:                     ((outline_include & INCLUDE_RIGHTONLY) && (state == STATE_FILERIGHTONLY))) {
        !          1205:                         i++;
        !          1206:                 }
        !          1207:         }
        !          1208: 
        !          1209: 
        !          1210:         /* allocate an array big enough for all of these */
        !          1211:         view->pItems = (COMPITEM FAR *) gmem_get(hHeap, i * sizeof(COMPITEM));
        !          1212:         view->rows = i;
        !          1213: 
        !          1214:         /* keep track of the column widths */
        !          1215:         view->maxtag = 0;
        !          1216:         view->maxrest = 0;
        !          1217: 
        !          1218:         /* loop through again filling the array, and at the same time looking
        !          1219:          * out for the handle of the previously expanded item
        !          1220:          */
        !          1221:         ci = (COMPITEM) List_First(li);
        !          1222:         for (i = 0; ci != NULL; ci = (COMPITEM) List_Next(ci)) {
        !          1223: 
        !          1224:                 state = compitem_getstate(ci);
        !          1225: 
        !          1226:                 if (((outline_include & INCLUDE_SAME) && (state == STATE_SAME)) ||
        !          1227:                     ((outline_include & INCLUDE_DIFFER) && (state == STATE_DIFFER)) ||
        !          1228:                     ((outline_include & INCLUDE_LEFTONLY) && (state == STATE_FILELEFTONLY)) ||
        !          1229:                     ((outline_include & INCLUDE_RIGHTONLY) && (state == STATE_FILERIGHTONLY))) {
        !          1230: 
        !          1231:                         view->pItems[i] = ci;
        !          1232: 
        !          1233:                         if (ci == view->ciSelect) {
        !          1234:                                 prev_row = i;
        !          1235:                         }
        !          1236: 
        !          1237:                         /* check the column widths in characters */
        !          1238:                         view->maxtag = max(view->maxtag,
        !          1239:                                            lstrlen(compitem_gettext_tag(ci)));
        !          1240:                         view->maxrest = max(view->maxrest,
        !          1241:                                             lstrlen(compitem_gettext_result(ci)));
        !          1242: 
        !          1243: 
        !          1244:                         i++;
        !          1245: 
        !          1246:                 }
        !          1247:         }
        !          1248:         ViewLeave();
        !          1249: 
        !          1250:         /* inform table of new layout of table - force refresh */       
        !          1251:         if (bRedraw) {
        !          1252:                 SendMessage(view->hwnd, TM_NEWLAYOUT, 0, (DWORD) view);
        !          1253:         
        !          1254:                 /* scroll to and highlight the row that represents the file
        !          1255:                  * we were previously expanding
        !          1256:                  */
        !          1257:                 if (prev_row != -1) {
        !          1258:                         select.startrow = prev_row;
        !          1259:                         select.startcell = 0;
        !          1260:                         select.nrows = 1;
        !          1261:                         select.ncells = 1;
        !          1262:                         SendMessage(view->hwnd, TM_SELECT, 0,
        !          1263:                                 (DWORD) (LPSTR) &select);
        !          1264:                 }
        !          1265:         }
        !          1266: }
        !          1267: 
        !          1268: 
        !          1269: /***************************************************************************
        !          1270:  * Function: view_expand_item
        !          1271:  *
        !          1272:  * Purpose:
        !          1273:  *
        !          1274:  * Expand a view - given the handle to the compitem to expand.
        !          1275:  *
        !          1276:  * Called from view_expand, and also to re-do an expanded view
        !          1277:  * after options change in view_changediffoptions and _changeviewoptions
        !          1278:  *
        !          1279:  * We get the composite section list from the compitem,
        !          1280:  * and pick out all the sections that are includable (according
        !          1281:  * to the global option expand_mode: we include all sections, or
        !          1282:  * just those in one side left or right). Once we know the count of rows,
        !          1283:  * allocate the mapping array: in each element of the array we keep
        !          1284:  * a handle to the section for that row (to get the state and hence the
        !          1285:  * tag text), and a handle to the line within that section (for the line text).
        !          1286:  *
        !          1287:  * We no longer insist on only expanding text files that differ - if the
        !          1288:  * compitem can give us a composite section list, we will map it.
        !          1289:  *
        !          1290:  * We need to be able to give a line number for a line, in either of
        !          1291:  * the original files according to which option is in force. Each section
        !          1292:  * can give us its base line number (number of first line in section) in
        !          1293:  * each of the two files or 0 if not present, and we track these here.
        !          1294:  *
        !          1295:  * MUST BE INSIDE CSView BEFORE CALLING HERE.
        !          1296:  */
        !          1297: BOOL
        !          1298: view_expand_item(VIEW view, COMPITEM ci)
        !          1299: {
        !          1300:         LIST li;
        !          1301:         SECTION sh;
        !          1302:         LINE line1, line2;
        !          1303:         int i, base_left, base_right, state;
        !          1304: 
        !          1305:         /* remember the compitem we are expanding */
        !          1306:         view->ciSelect = ci;
        !          1307: 
        !          1308:         /* get the composite section list */
        !          1309:         li = compitem_getcomposite(view->ciSelect);
        !          1310:         if (li == NULL) {
        !          1311:                 ViewLeave();
        !          1312:                 return FALSE;
        !          1313:         }
        !          1314: 
        !          1315:         /* switch modes and free the current mapping
        !          1316:          *
        !          1317:          * NOTE: must do this AFTER the compitem_getcomposite,
        !          1318:          * since that can fail: if it fails it could put up a
        !          1319:          * message box, and that could cause a queued paint message
        !          1320:          * to be processed, which would cause us to use these mappings
        !          1321:          * and gpfault if they had been cleared first.
        !          1322:          */
        !          1323:         view->bExpand = TRUE;
        !          1324:         view_freemappings(view);
        !          1325: 
        !          1326: 
        !          1327:         /* loop through totalling the lines in sections
        !          1328:          * that we should include
        !          1329:          */
        !          1330:         view->rows = 0;
        !          1331:         for (sh = (SECTION) List_First(li); sh != NULL;
        !          1332:             sh = (SECTION) List_Next(sh)) {
        !          1333:                 
        !          1334:                 state = section_getstate(sh);
        !          1335:                 
        !          1336:                 if (expand_mode == IDM_RONLY) {
        !          1337:                         if ((state == STATE_LEFTONLY) ||
        !          1338:                             (state == STATE_MOVEDLEFT)) {
        !          1339:                                     continue;
        !          1340:                         }
        !          1341:                 } else if (expand_mode == IDM_LONLY) {
        !          1342:                         if ((state == STATE_RIGHTONLY) ||
        !          1343:                             (state == STATE_MOVEDRIGHT)) {
        !          1344:                                     continue;
        !          1345:                         }
        !          1346:                 }
        !          1347: 
        !          1348:                 /* include all lines in this section */
        !          1349:                 view->rows += section_getlinecount(sh);
        !          1350:         }
        !          1351:         
        !          1352:         /* allocate the memory for the mapping array */
        !          1353:         view->pLines = (PVIEWLINE) gmem_get(hHeap, view->rows * sizeof(VIEWLINE));
        !          1354:         
        !          1355:         /* loop through the sections again filling in the mapping array */
        !          1356:         i = 0;
        !          1357:         view->maxtag = 5;
        !          1358:         view->maxrest = 0;
        !          1359:         for (sh = (SECTION) List_First(li); sh != NULL;
        !          1360:             sh = (SECTION) List_Next(sh)) {
        !          1361:                 
        !          1362:                 state = section_getstate(sh);
        !          1363:                 
        !          1364:                 if (expand_mode == IDM_RONLY) {
        !          1365:                         if ((state == STATE_LEFTONLY) ||
        !          1366:                             (state == STATE_MOVEDLEFT)) {
        !          1367:                                     continue;
        !          1368:                         }
        !          1369:                 } else if (expand_mode == IDM_LONLY) {
        !          1370:                         if ((state == STATE_RIGHTONLY) ||
        !          1371:                             (state == STATE_MOVEDRIGHT)) {
        !          1372:                                     continue;
        !          1373:                         }
        !          1374:                 }
        !          1375: 
        !          1376:                 /* find the base line number in each file */
        !          1377:                 base_left = section_getleftbasenr(sh);
        !          1378:                 base_right = section_getrightbasenr(sh);
        !          1379: 
        !          1380:                 /* add each line in section to the view. section_getfirst()
        !          1381:                  * returns us to a handle that is in a list. We can
        !          1382:                  * call List_Next and will eventually get to the
        !          1383:                  * line returned by section_getlast(). Sections always have
        !          1384:                  * at least one line
        !          1385:                  */
        !          1386:                 line1 = section_getfirstline(sh);
        !          1387:                 line2 = section_getlastline(sh);
        !          1388: 
        !          1389:                 for (; line1 != NULL; line1 = (LINE) List_Next(line1)) {
        !          1390: 
        !          1391:                         view->pLines[i].line = line1;
        !          1392:                         view->pLines[i].section = sh;
        !          1393: 
        !          1394:                         /* calculate the line number for this line by
        !          1395:                          * incrementing the base nr for this section
        !          1396:                          */
        !          1397:                 
        !          1398:                         view->pLines[i].nr_left = base_left;
        !          1399:                         if (base_left != 0) {
        !          1400:                                 base_left++;
        !          1401:                         }
        !          1402: 
        !          1403:                         view->pLines[i].nr_right = base_right;
        !          1404:                         if (base_right != 0) {
        !          1405:                                 base_right++;
        !          1406:                         }
        !          1407: 
        !          1408:                         /* increment index into view */
        !          1409:                         i++;
        !          1410: 
        !          1411:                         /* check the column widths */
        !          1412:                         view->maxrest = max(view->maxrest,
        !          1413:                                             (line_gettabbedlength(line1, 8)));
        !          1414: 
        !          1415:                         /* end of section ? */
        !          1416:                         if (line1 == line2) {
        !          1417:                                 break;
        !          1418:                         }
        !          1419:                 }
        !          1420:         }
        !          1421: 
        !          1422:         /* We must NOT hold a critical section here as SendMessage may hang */
        !          1423:         ViewLeave();
        !          1424: 
        !          1425:         /*inform table window of revised mapping */
        !          1426:         SendMessage(view->hwnd, TM_NEWLAYOUT, 0, (DWORD) view);
        !          1427: 
        !          1428:         return(TRUE);
        !          1429: }
        !          1430: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.