Annotation of mstools/samples/sdktools/windiff/view.c, revision 1.1.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.