File: brgrids.g

package info (click to toggle)
gap-browse 1.8.21%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,296 kB
  • sloc: xml: 1,961; ansic: 1,342; makefile: 163; javascript: 155; sh: 20
file content (420 lines) | stat: -rw-r--r-- 16,665 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#############################################################################
##
#W  brgrids.g             GAP 4 package `browse'                Thomas Breuer
##
##  This file contains some <C>SpecialGrid</C> functions.
##

#T TB, May 2007:
#T extended version of `NCurses.Grid',
#T supports ``indicating continuation'' and attributes for lines;
#T the optional components `tend', `bend', `lend', `rend' are `true'
#T if the shown grid is not continued at the top, bottom, left, and right,
#T respectively (this is also the default), and `false' otherwise;
#T the argument `attrs', if given, must be an integer
#T describing the attributes for the lines.

NCurses.GridExt:= function( win, args, attrs )
  local size, trow, brow, lcol, rcol, rowinds, colinds,
        tend, bend, lend, rend,
        tvis, bvis, ht, lvis, rvis, wdth, ld, lmr, i, j;

  size := NCurses.getmaxyx(win);
  if size = false then return false; fi;

  trow:= args.trow;
  brow:= args.brow;
  lcol:= args.lcol;
  rcol:= args.rcol;
  rowinds:= args.rowinds;
  colinds:= args.colinds;
  tend:= not IsBound( args.tend ) or args.tend = true;
  bend:= not IsBound( args.bend ) or args.bend = true;
  lend:= not IsBound( args.lend ) or args.lend = true;
  rend:= not IsBound( args.rend ) or args.rend = true;

  if not ForAll([trow, brow, lcol, rcol], IsInt) then return false; fi;
  if not ForAll(rowinds, IsInt) then return false; fi;
  if not ForAll(colinds, IsInt) then return false; fi;
  # find viewable rows and cols
  rowinds := Filtered(rowinds, i-> i >= 0 and i >= trow and
                                   i <= size[1]-1 and i <= brow);
  colinds := Filtered(colinds, i-> i >= 0 and i >= lcol and
                                   i <= size[2]-1 and i <= rcol);
  if IsEmpty( rowinds ) and IsEmpty( colinds ) then
    return false;
  fi;
  tvis := Maximum(trow, 0);
  bvis := Minimum(brow, size[1]);
  ht := bvis - tvis + 1;
  lvis := Maximum(lcol, 0);
  rvis := Minimum(rcol, size[2]);
  wdth := rvis - lvis + 1;
  # Set attributes for the lines.
  NCurses.wattrset( win, attrs );
  # draw vlines
  ld := NCurses.lineDraw;
  for i in colinds do
    NCurses.wmove(win, tvis, i);
    NCurses.wvline(win, ld.VLINE, ht);
  od;
  # draw hlines and handle crossings
  for i in rowinds do
    NCurses.wmove(win, i, lvis);
    NCurses.whline(win, ld.HLINE, wdth);
    if i = trow and tend then
      lmr := [ld.ULCORNER, ld.TTEE, ld.URCORNER];
    elif i = brow and bend then
      lmr := [ld.LLCORNER, ld.BTEE, ld.LRCORNER];
    else
      lmr := [ld.LTEE, ld.PLUS, ld.RTEE];
    fi;
    for j in colinds do
      NCurses.wmove(win, i, j);
      if j = lcol and lend then
        NCurses.waddch(win, lmr[1]);
      elif j = rcol and rend then
        NCurses.waddch(win, lmr[3]);
      else
        NCurses.waddch(win, lmr[2]);
      fi;
    od;
  od;
  # Reset the attributes.
  NCurses.wattrset( win, NCurses.attrs.NORMAL );
  return true;
end;


#############################################################################
##
#F  BrowseData.SpecialGridLineDraw( <t>, <data> )
##
##  When this special grid is used in a browse table,
##  nonempty row separators are overwritten with horizontal rows
##  that consist of the special character <C>NCurses.lineDraw.HLINE</C>,
##  non-blank characters in column separators are overwritten with vertical
##  rows that consist of the special character <C>NCurses.lineDraw.VLINE</C>,
##  and <Q>crossings</Q> of horizontal and vertical lines are handled as in
##  <Ref Func="NCurses.Grid"/>.
##  <P/>
##  In categorized browse tables, each set of table rows shown under
##  a category row gets a grid of its own,
##  and the separators below category rows are regarded as the top rows of
##  these grids.
##  So this special grid requires nonempty category separators if nonempty
##  row separators occur.
##  (Note that below a row separator, first the category rows and their
##  separators appear, and then the data rows and their separators.
##  If there is a nonempty row separator above the first data row
##  then it is overwritten by whitespace.)
##
BrowseData.SpecialGridLineDraw:= function( t, data )
    local win, entry, top, i;

    win:= t.dynamic.window;

    # Clear category separators, since they may exceed the last column.
    for entry in data.catSeparators do
      NCurses.wmove( win, entry[1], entry[2] );
      NCurses.waddstr( win, ListWithIdenticalEntries( entry[3], ' ' ) );
    od;

    # Replace the row and column separators in all four tables by the lines.
    for entry in data.gridsInfo do
      NCurses.GridExt( win, entry, NCurses.attrs.NORMAL );
    od;

    # Overwrite a row separator above the first data row
    # if the table has a category for the first data row.
    top:= t.dynamic.topleft[1];
    if IsOddInt( top )
       and t.dynamic.topleft[3] = 1
       and BrowseData.LengthCell( t, top, "vert" ) <> 0 then
      for i in [ top+1, top+3 .. Length( t.dynamic.indexRow ) - 1 ] do
        if BrowseData.LengthCell( t, i, "vert" ) <> 0 then
          if i in t.dynamic.categories[1] then
            NCurses.wmove( win, data.topmargin + data.headerLength
                                + BrowseData.HeightLabelsColTable( t ),
                           data.leftmargin );
            NCurses.waddstr( win, ListWithIdenticalEntries(
                NCurses.getmaxyx( win )[2] - data.leftmargin, ' ' ) );
          fi;
          break;
        fi;
      od;
    fi;

    # Print those category separators that do not overwrite grid top lines.
#T force printing of category separators involving attributes!
    for entry in data.catSeparators do
      if ForAll( data.gridsInfo, x -> entry[1] <> x.trow ) then
        NCurses.wmove( win, entry[1], entry[2] );
        NCurses.whline( win, NCurses.lineDraw.HLINE, entry[3] );
      fi;
    od;
end;


#############################################################################
##
#F  BrowseData.SpecialGridLineDrawPlus( <t>, <data> )
##
##  This function is used for example in the `Browse' method for matrices.
##
##  It draws the crossing of the two lines that separate the row and column
##  labels from the main table.
##  Note that the grids drawn by `BrowseData.SpecialGridLineDraw' belong to
##  one of the four subtables of a browse table, and it is not supported
##  that lines separate these tables.
##
BrowseData.SpecialGridLineDrawPlus:= function( t, data )
    local win;

    BrowseData.SpecialGridLineDraw( t, data );
    win:= t.dynamic.window;
    NCurses.wmove( win, data.gridsInfo[1].rowinds[1],
                        data.gridsInfo[1].colinds[1] );
    NCurses.waddch( win, NCurses.lineDraw.PLUS );
end;


#############################################################################
##
#F  BrowseData.SpecialGridTreeStyle( <t>, <data> )
##
##  *NOTE*:
##  This function does not yet support category separators
##  and cells of height larger than 1.
##  (And there is the general problem that when one expands all categories at
##  the end of the table, the programmatically hidden rows are taken into
##  account and then lead to unmotivated empty rows.)
##  (Scrolling by cells seems to be not appropriate for this application,
##  scrolling by characters would be better.)
##
BrowseData.SpecialGridTreeStyle:= function( t, data )
    local categories, catpos, win, i, fromrow, maxdepth, previousrow, scr,
          ymin, ymax, y, prevdatarow, pos, entry, level, currlevel, pos2,
          kmin, j, k, lastcategorypos, height, l;

    categories:= t.dynamic.categories;
    catpos:= categories[1];
    if IsEmpty( catpos ) or 2 < catpos[1] then
      # `BrowseData.SpecialGridTreeStyle' expects category rows,
      # starting in the first row.
      return;
    fi;
    win:= t.dynamic.window;
    i:= t.dynamic.topleft[1];
    fromrow:= t.dynamic.topleft[3];
    maxdepth:= Length( t.work.sepCol[1] );

    # The `i'-th entry in `previousrow' is the position of the previous
    # level `i' category if there is one on the screen, and zero otherwise.
    previousrow:= 0 * [ 0 .. maxdepth ];

    # Process the current line.
    scr:= BrowseData.HeightWidthWindow( t );
    ymin:= data.topmargin + BrowseData.HeightLabelsColTable( t )
                          + data.headerLength + 1;
    ymax:= scr[1] - data.bottommargin - data.footerLength;
    y:= ymin;
    prevdatarow:= fail;
    while y <= ymax+1 and IsBound( t.dynamic.indexRow[i] ) do
      # We consider row `ymax+1' but we do not print there.
      if i mod 2 = 0 then

        # Deal with categories, omitting the first `fromrow - 1' rows.
        pos:= PositionSorted( catpos, i );
#T Why is there no variant with a <from> argument?
        while pos <= Length( catpos ) and catpos[ pos ] = i do
          entry:= categories[2][ pos ];
          if entry.isUnderCollapsedCategory or entry.isRejectedCategory then
            # This category and all of higher level are hidden.
            break;
          fi;
          level:= entry.level;

          # Deal with the category line.
          if 1 < fromrow then
            # The beginning of the cell is above the screen.
            fromrow:= fromrow - 1;
          else
            # (We print no path to level 1 rows.)
            if 1 < level then
              if not IsBound( currlevel ) then
                # The current level is that of the previous category row.
                pos2:= pos;
                while 1 < pos2 and catpos[ pos2 ] = i do
                  pos2:= pos2 - 1;
                od;
                currlevel:= categories[2][ pos2 ].level;
              fi;

              # Print the grid part for this level above the current line.
              if   currlevel < level then
                # Fill the level `currlevel' column above the current line.
                if ymin < y and previousrow[ currlevel ] + 1 < y then
                  NCurses.wmove( win, y-2, 0 );
                  NCurses.waddstr( win, ListWithIdenticalEntries(
                                            2*currlevel-2, ' ' ) );
                  NCurses.wmove( win, y-2, 2*currlevel-2 );
                  NCurses.waddch( win, NCurses.lineDraw.LTEE );
                fi;
              elif currlevel = level then
                # Fill the level `currlevel' column above the current line.
                if previousrow[ currlevel ] = 0 then
                  kmin:= ymin;
                  NCurses.wmove( win, kmin-1, 0 );
                  NCurses.waddstr( win, ListWithIdenticalEntries(
                                            2*currlevel-4, ' ' ) );
                  NCurses.wmove( win, kmin - 1, 2*currlevel-4 );
                  NCurses.waddch( win, NCurses.lineDraw.VLINE );
                else
                  kmin:= previousrow[ currlevel ];
                  NCurses.wmove( win, kmin-1, 0 );
                  NCurses.waddstr( win, ListWithIdenticalEntries(
                                            2*currlevel-4, ' ' ) );
                  NCurses.wmove( win, kmin - 1, 2*currlevel-4 );
                  NCurses.waddch( win, NCurses.lineDraw.LTEE );
                fi;
                NCurses.wmove( win, kmin, 2 * ( currlevel-2 ) );
                NCurses.wvline( win, NCurses.lineDraw.VLINE, y - kmin - 1 );
              else
                # Fill the column for level `level' above the current line.
                if previousrow[ level ] = 0 then
                  kmin:= ymin;
                else
                  kmin:= previousrow[ level ];
                fi;
                NCurses.wmove( win, kmin-1, 0 );
                NCurses.waddstr( win, ListWithIdenticalEntries(
                                          2*level-4, ' ' ) );
                NCurses.wmove( win, kmin - 1, 2*level-4 );
                if previousrow[ level ] = 0 then
                  NCurses.waddch( win, NCurses.lineDraw.VLINE );
                else
                  NCurses.waddch( win, NCurses.lineDraw.LTEE );
                fi;
                NCurses.wmove( win, kmin, 2 * ( level-2 ) );
                NCurses.wvline( win, NCurses.lineDraw.VLINE, y - kmin - 1 );
              fi;
              if y <= ymax then
                NCurses.wmove( win, y-1, 0 );
                NCurses.waddstr( win, ListWithIdenticalEntries(
                                          2*level-4, ' ' ) );
                NCurses.wmove( win, y-1, 2*level-4 );
                NCurses.waddch( win, NCurses.lineDraw.LLCORNER );
              fi;
            fi;
            previousrow[ level ]:= y;
            currlevel:= level;
            lastcategorypos:= pos;

            y:= y + 1;
          fi;

          pos:= pos + 1;
        od;
      fi;

      # Deal with the data rows.
#T what about fromrow?
      height:= BrowseData.HeightRow( t, i );
      if 0 < height then
        if i mod 2 = 0 then
          if not IsBound( currlevel ) then
            # The first shown row is a data row.
            # Determine the level of the category row above the first line.
            pos:= PositionSorted( catpos, i );
            if IsBound( catpos[ pos ] ) and catpos[ pos ] = i then
              if BrowseData.HeightCategories( t, i ) < fromrow then
                # Take the last category row for `i'.
                while IsBound( catpos[ pos ] ) and catpos[ pos ] = i do
                  pos:= pos + 1;
                od;
              else
                # Take the last category row for `i' above the first line,
                # together with its category separator below.
                while IsBound( catpos[ pos ] )
                      and BrowseData.HeightCategories( t, i,
                              categories[2][ pos ].level ) < fromrow do
                  pos:= pos + 1;
                od;
              fi;
            fi;
            if 1 < pos then
              pos:= pos-1;
            fi;
            currlevel:= categories[2][ pos ].level;
            lastcategorypos:= pos;
          fi;

          # Fill the column for level `currlevel' above the current line.
          if prevdatarow = y-1 then
            NCurses.wmove( win, y-2, 0 );
            NCurses.waddstr( win, ListWithIdenticalEntries(
                                      2*currlevel-2, ' ' ) );
            NCurses.wmove( win, y-2, 2*currlevel-2 );
            NCurses.waddch( win, NCurses.lineDraw.LTEE );
          fi;
          if y <= ymax then
            NCurses.wmove( win, y-1, 0 );
            NCurses.waddstr( win, ListWithIdenticalEntries(
                                      2*currlevel-2, ' ' ) );
            NCurses.wmove( win, y-1, 2*currlevel-2 );
            NCurses.waddch( win, NCurses.lineDraw.LLCORNER );
          fi;
          prevdatarow:= y;
#T fill with LTEE only in the first line of a cell, otherwise with VLINE
          # Draw a horizontal line in row `y'.
          if y <= ymax then
            NCurses.wmove( win, y-1, 2 * currlevel - 1 );
            NCurses.whline( win, NCurses.lineDraw.HLINE,
                            2 * ( maxdepth - currlevel ) );
          fi;
        fi;
        y:= y + height - fromrow + 1;
      fi;
      i:= i + 1;
      fromrow:= 1;
    od;

    # Draw the missing vertical lines from and to outside categories:
    # If there is an unhidden category of level $k$ below and above
    # the next category of level less than $k$
    # then either replace the `LLCORNER' in column $k-1$ by an `LTEE' and
    # draw a `VLINE' below until the end of the window,
    # or in the case that there is no `LLCORNER' in column $k-1$
    # draw a `VLINE' through the whole window.
    for k in [ 2 .. Length( previousrow ) ] do
      if previousrow[k] >= previousrow[ k-1 ] then
        for pos2 in [ lastcategorypos + 1 .. Length( catpos ) ] do
          if   categories[2][ pos2 ].level = k
               and not categories[2][ pos2 ].isRejectedCategory then
            if previousrow[k] = 0 then
              NCurses.wmove( win, ymin - 1, 2 * ( k-2 ) );
              NCurses.wvline( win, NCurses.lineDraw.VLINE,
                              ymax - ymin + 1 );
            elif previousrow[k] <= ymax then
              NCurses.wmove( win, previousrow[k]-1, 2 * ( k-2 ) );
              NCurses.waddch( win, NCurses.lineDraw.LTEE );
              NCurses.wmove( win, previousrow[k], 2 * ( k-2 ) );
              NCurses.wvline( win, NCurses.lineDraw.VLINE,
                              ymax - previousrow[k] );
            fi;
            break;
          elif categories[2][ pos2 ].level < k
               and not categories[2][ pos2 ].isRejectedCategory then
            break;
          fi;
        od;
      fi;
    od;
end;


#############################################################################
##
#E