slithernix-cdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cdk/viewer.rb ADDED
@@ -0,0 +1,812 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class VIEWER < CDK::CDKOBJS
5
+ DOWN = 0
6
+ UP = 1
7
+
8
+ def initialize(cdkscreen, xplace, yplace, height, width,
9
+ buttons, button_count, button_highlight, box, shadow)
10
+ super()
11
+ parent_width = cdkscreen.window.maxx
12
+ parent_height = cdkscreen.window.maxy
13
+ box_width = width
14
+ box_height = height
15
+ button_width = 0
16
+ button_adj = 0
17
+ button_pos = 1
18
+ bindings = {
19
+ CDK::BACKCHAR => Curses::KEY_PPAGE,
20
+ 'b' => Curses::KEY_PPAGE,
21
+ 'B' => Curses::KEY_PPAGE,
22
+ CDK::FORCHAR => Curses::KEY_NPAGE,
23
+ ' ' => Curses::KEY_NPAGE,
24
+ 'f' => Curses::KEY_NPAGE,
25
+ 'F' => Curses::KEY_NPAGE,
26
+ '|' => Curses::KEY_HOME,
27
+ '$' => Curses::KEY_END,
28
+ }
29
+
30
+ self.setBox(box)
31
+
32
+ box_height = CDK.setWidgetDimension(parent_height, height, 0)
33
+ box_width = CDK.setWidgetDimension(parent_width, width, 0)
34
+
35
+ # Rejustify the x and y positions if we need to.
36
+ xtmp = [xplace]
37
+ ytmp = [yplace]
38
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
39
+ xpos = xtmp[0]
40
+ ypos = ytmp[0]
41
+
42
+ # Make the viewer window.
43
+ @win= Curses::Window.new(box_height, box_width, ypos, xpos)
44
+ if @win.nil?
45
+ self.destroy
46
+ return nil
47
+ end
48
+
49
+ # Turn the keypad on for the viewer.
50
+ @win.keypad(true)
51
+
52
+ # Create the buttons.
53
+ @button_count = button_count
54
+ @button = []
55
+ @button_len = []
56
+ @button_pos = []
57
+ if button_count > 0
58
+ (0...button_count).each do |x|
59
+ button_len = []
60
+ @button << CDK.char2Chtype(buttons[x], button_len, [])
61
+ @button_len << button_len[0]
62
+ button_width += @button_len[x] + 1
63
+ end
64
+ button_adj = (box_width - button_width) / (button_count + 1)
65
+ button_pos = 1 + button_adj
66
+ (0...button_count).each do |x|
67
+ @button_pos << button_pos
68
+ button_pos += button_adj + @button_len[x]
69
+ end
70
+ end
71
+
72
+ # Set the rest of the variables.
73
+ @screen = cdkscreen
74
+ @parent = cdkscreen.window
75
+ @shadow_win = nil
76
+ @button_highlight = button_highlight
77
+ @box_height = box_height
78
+ @box_width = box_width - 2
79
+ @view_size = height - 2
80
+ @input_window = @win
81
+ @shadow = shadow
82
+ @current_button = 0
83
+ @current_top = 0
84
+ @length = 0
85
+ @left_char = 0
86
+ @max_left_char = 0
87
+ @max_top_line = 0
88
+ @characters = 0
89
+ @list_size = -1
90
+ @show_line_info = 1
91
+ @exit_type = :EARLY_EXIT
92
+
93
+ # Do we need to create a shadow?
94
+ if shadow
95
+ @shadow_win = Curses::Window.new(box_height, box_width + 1,
96
+ ypos + 1, xpos + 1)
97
+ if @shadow_win.nil?
98
+ self.destroy
99
+ return nil
100
+ end
101
+ end
102
+
103
+ # Setup the key bindings.
104
+ bindings.each do |from, to|
105
+ self.bind(:VIEWER, from, :getc, to)
106
+ end
107
+
108
+ cdkscreen.register(:VIEWER, self)
109
+ end
110
+
111
+ # This function sets various attributes of the widget.
112
+ def set(title, list, list_size, button_highlight,
113
+ attr_interp, show_line_info, box)
114
+ self.setTitle(title)
115
+ self.setHighlight(button_highlight)
116
+ self.setInfoLine(show_line_info)
117
+ self.setBox(box)
118
+ return self.setInfo(list, list_size, attr_interp)
119
+ end
120
+
121
+ # This sets the title of the viewer. (A nil title is allowed.
122
+ # It just means that the viewer will not have a title when drawn.)
123
+ def setTitle(title)
124
+ super(title, -(@box_width + 1))
125
+ @title_adj = @title_lines
126
+
127
+ # Need to set @view_size
128
+ @view_size = @box_height - (@title_lines + 1) - 2
129
+ end
130
+
131
+ def getTitle
132
+ return @title
133
+ end
134
+
135
+ def setupLine(interpret, list, x)
136
+ # Did they ask for attribute interpretation?
137
+ if interpret
138
+ list_len = []
139
+ list_pos = []
140
+ @list[x] = CDK.char2Chtype(list, list_len, list_pos)
141
+ @list_len[x] = list_len[0]
142
+ @list_pos[x] = CDK.justifyString(@box_width, @list_len[x], list_pos[0])
143
+ else
144
+ # We must convert tabs and other nonprinting characters. The curses
145
+ # library normally does this, but we are bypassing it by writing
146
+ # chtypes directly.
147
+ t = ''
148
+ len = 0
149
+ (0...list.size).each do |y|
150
+ if list[y] == "\t".ord
151
+ begin
152
+ t << ' '
153
+ len += 1
154
+ end while (len & 7) != 0
155
+ elsif CDK.CharOf(list[y].ord).match(/^[[:print:]]$/)
156
+ t << CDK.CharOf(list[y].ord)
157
+ len += 1
158
+ else
159
+ t << Curses.unctrl(list[y].ord)
160
+ len += 1
161
+ end
162
+ end
163
+ @list[x] = t
164
+ @list_len[x] = t.size
165
+ @list_pos[x] = 0
166
+ end
167
+ @widest_line = [@widest_line, @list_len[x]].max
168
+ end
169
+
170
+ def freeLine(x)
171
+ if x < @list_size
172
+ @list[x] = ''
173
+ end
174
+ end
175
+
176
+ # This function sets the contents of the viewer.
177
+ def setInfo(list, list_size, interpret)
178
+ current_line = 0
179
+ viewer_size = list_size
180
+
181
+ if list_size < 0
182
+ list_size = list.size
183
+ end
184
+
185
+ # Compute the size of the resulting display
186
+ viewer_size = list_size
187
+ if list.size > 0 && interpret
188
+ (0...list_size).each do |x|
189
+ filename = ''
190
+ if CDK.checkForLink(list[x], filename) == 1
191
+ file_contents = []
192
+ file_len = CDK.readFile(filename, file_contents)
193
+
194
+ if file_len >= 0
195
+ viewer_size += (file_len - 1)
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ # Clean out the old viewer info. (if there is any)
202
+ @in_progress = true
203
+ self.clean
204
+ self.createList(viewer_size)
205
+
206
+ # Keep some semi-permanent info
207
+ @interpret = interpret
208
+
209
+ # Copy the information given.
210
+ current_line = 0
211
+ x = 0
212
+ while x < list_size && current_line < viewer_size
213
+ if list[x].size == 0
214
+ @list[current_line] = ''
215
+ @list_len[current_line] = 0
216
+ @list_pos[current_line] = 0
217
+ current_line += 1
218
+ else
219
+ # Check if we have a file link in this line.
220
+ filename = []
221
+ if CDK.checkForLink(list[x], filename) == 1
222
+ # We have a link, open the file.
223
+ file_contents = []
224
+ file_len = 0
225
+
226
+ # Open the file and put it into the viewer
227
+ file_len = CDK.readFile(filename, file_contents)
228
+ if file_len == -1
229
+ fopen_fmt = if Curses.has_colors?
230
+ then '<C></16>Link Failed: Could not open the file %s'
231
+ else '<C></K>Link Failed: Could not open the file %s'
232
+ end
233
+ temp = fopen_fmt % filename
234
+ self.setupLine(true, temp, current_line)
235
+ current_line += 1
236
+ else
237
+ # For each line read, copy it into the viewer.
238
+ file_len = [file_len, viewer_size - current_line].min
239
+ (0...file_len).each do |file_line|
240
+ if current_line >= viewer_size
241
+ break
242
+ end
243
+ self.setupLine(false, file_contents[file_line], current_line)
244
+ @characters += @list_len[current_line]
245
+ current_line += 1
246
+ end
247
+ end
248
+ elsif current_line < viewer_size
249
+ self.setupLine(@interpret, list[x], current_line)
250
+ @characters += @list_len[current_line]
251
+ current_line += 1
252
+ end
253
+ end
254
+ x+= 1
255
+ end
256
+
257
+ # Determine how many characters we can shift to the right before
258
+ # all the items have been viewer off the screen.
259
+ if @widest_line > @box_width
260
+ @max_left_char = (@widest_line - @box_width) + 1
261
+ else
262
+ @max_left_char = 0
263
+ end
264
+
265
+ # Set up the needed vars for the viewer list.
266
+ @in_progress = false
267
+ @list_size = viewer_size
268
+ if @list_size <= @view_size
269
+ @max_top_line = 0
270
+ else
271
+ @max_top_line = @list_size - 1
272
+ end
273
+ return @list_size
274
+ end
275
+
276
+ def getInfo(size)
277
+ size << @list_size
278
+ return @list
279
+ end
280
+
281
+ # This function sets the highlight type of the buttons.
282
+ def setHighlight(button_highlight)
283
+ @button_highlight = button_highlight
284
+ end
285
+
286
+ def getHighlight
287
+ return @button_highlight
288
+ end
289
+
290
+ # This sets whether or not you wnat to set the viewer info line.
291
+ def setInfoLine(show_line_info)
292
+ @show_line_info = show_line_info
293
+ end
294
+
295
+ def getInfoLine
296
+ return @show_line_info
297
+ end
298
+
299
+ # This removes all the lines inside the scrolling window.
300
+ def clean
301
+ # Clean up the memory used...
302
+ (0...@list_size).each do |x|
303
+ self.freeLine(x)
304
+ end
305
+
306
+ # Reset some variables.
307
+ @list_size = 0
308
+ @max_left_char = 0
309
+ @widest_line = 0
310
+ @current_top = 0
311
+ @max_top_line = 0
312
+
313
+ # Redraw the window.
314
+ self.draw(@box)
315
+ end
316
+
317
+ def PatternNotFound(pattern)
318
+ temp_info = [
319
+ "</U/5>Pattern '%s' not found.<!U!5>" % pattern,
320
+ ]
321
+ self.popUpLabel(temp_info)
322
+ end
323
+
324
+ # This function actually controls the viewer...
325
+ def activate(actions)
326
+ refresh = false
327
+ # Create the information about the file stats.
328
+ file_info = [
329
+ '</5> </U>File Statistics<!U> <!5>',
330
+ '</5> <!5>',
331
+ '</5/R>Character Count:<!R> %-4d <!5>' % @characters,
332
+ '</5/R>Line Count :<!R> %-4d <!5>' % @list_size,
333
+ '</5> <!5>',
334
+ '<C></5>Press Any Key To Continue.<!5>'
335
+ ]
336
+
337
+ temp_info = ['<C></5>Press Any Key To Continue.<!5>']
338
+
339
+ # Set the current button.
340
+ @current_button = 0
341
+
342
+ # Draw the widget list.
343
+ self.draw(@box)
344
+
345
+ # Do this until KEY_ENTER is hit.
346
+ while true
347
+ # Reset the refresh flag.
348
+ refresh = false
349
+
350
+ input = self.getch([])
351
+ if !self.checkBind(:VIEWER, input)
352
+ case input
353
+ when CDK::KEY_TAB
354
+ if @button_count > 1
355
+ if @current_button == @button_count - 1
356
+ @current_button = 0
357
+ else
358
+ @current_button += 1
359
+ end
360
+
361
+ # Redraw the buttons.
362
+ self.drawButtons
363
+ end
364
+ when CDK::PREV
365
+ if @button_count > 1
366
+ if @current_button == 0
367
+ @current_button = @button_count - 1
368
+ else
369
+ @current_button -= 1
370
+ end
371
+
372
+ # Redraw the buttons.
373
+ self.drawButtons
374
+ end
375
+ when Curses::KEY_UP
376
+ if @current_top > 0
377
+ @current_top -= 1
378
+ refresh = true
379
+ else
380
+ CDK.Beep
381
+ end
382
+ when Curses::KEY_DOWN
383
+ if @current_top < @max_top_line
384
+ @current_top += 1
385
+ refresh = true
386
+ else
387
+ CDK.Beep
388
+ end
389
+ when Curses::KEY_RIGHT
390
+ if @left_char < @max_left_char
391
+ @left_char += 1
392
+ refresh = true
393
+ else
394
+ CDK.Beep
395
+ end
396
+ when Curses::KEY_LEFT
397
+ if @left_char > 0
398
+ @left_char -= 1
399
+ refresh = true
400
+ else
401
+ CDK.Beep
402
+ end
403
+ when Curses::KEY_PPAGE
404
+ if @current_top > 0
405
+ if @current_top - (@view_size - 1) > 0
406
+ @current_top = @current_top - (@view_size - 1)
407
+ else
408
+ @current_top = 0
409
+ end
410
+ refresh = true
411
+ else
412
+ CDK.Beep
413
+ end
414
+ when Curses::KEY_NPAGE
415
+ if @current_top < @max_top_line
416
+ if @current_top + @view_size < @max_top_line
417
+ @current_top = @current_top + (@view_size - 1)
418
+ else
419
+ @current_top = @max_top_line
420
+ end
421
+ refresh = true
422
+ else
423
+ CDK.Beep
424
+ end
425
+ when Curses::KEY_HOME
426
+ @left_char = 0
427
+ refresh = true
428
+ when Curses::KEY_END
429
+ @left_char = @max_left_char
430
+ refresh = true
431
+ when 'g', '1', '<'
432
+ @current_top = 0
433
+ refresh = true
434
+ when 'G', '>'
435
+ @current_top = @max_top_line
436
+ refresh = true
437
+ when 'L'
438
+ x = (@list_size + @current_top) / 2
439
+ if x < @max_top_line
440
+ @current_top = x
441
+ refresh = true
442
+ else
443
+ CDK.Beep
444
+ end
445
+ when 'l'
446
+ x = @current_top / 2
447
+ if x >= 0
448
+ @current_top = x
449
+ refresh = true
450
+ else
451
+ CDK.Beep
452
+ end
453
+ when '?'
454
+ @search_direction = CDK::VIEWER::UP
455
+ self.getAndStorePattern(@screen)
456
+ if !self.searchForWord(@search_pattern, @search_direction)
457
+ self.PatternNotFound(@search_pattern)
458
+ end
459
+ refresh = true
460
+ when '/'
461
+ @search_direction = CDK::VIEWER:DOWN
462
+ self.getAndStorePattern(@screen)
463
+ if !self.searchForWord(@search_pattern, @search_direction)
464
+ self.PatternNotFound(@search_pattern)
465
+ end
466
+ refresh = true
467
+ when 'N', 'n'
468
+ if @search_pattern == ''
469
+ temp_info[0] = '</5>There is no pattern in the buffer.<!5>'
470
+ self.popUpLabel(temp_info)
471
+ elsif !self.searchForWord(@search_pattern,
472
+ if input == 'n'
473
+ then @search_direction
474
+ else 1 - @search_direction
475
+ end)
476
+ self.PatternNotFound(@search_pattern)
477
+ end
478
+ refresh = true
479
+ when ':'
480
+ @current_top = self.jumpToLine
481
+ refresh = true
482
+ when 'i', 's', 'S'
483
+ self.popUpLabel(file_info)
484
+ refresh = true
485
+ when CDK::KEY_ESC
486
+ self.setExitType(input)
487
+ return -1
488
+ when Curses::Error
489
+ self.setExitType(input)
490
+ return -1
491
+ when Curses::KEY_ENTER, CDK::KEY_RETURN
492
+ self.setExitType(input)
493
+ return @current_button
494
+ when CDK::REFRESH
495
+ @screen.erase
496
+ @screen.refresh
497
+ else
498
+ CDK.Beep
499
+ end
500
+ end
501
+
502
+ # Do we need to redraw the screen?
503
+ if refresh
504
+ self.drawInfo
505
+ end
506
+ end
507
+ end
508
+
509
+ # This searches the document looking for the given word.
510
+ def getAndStorePattern(screen)
511
+ temp = ''
512
+
513
+ # Check the direction.
514
+ if @search_direction == CDK::VIEWER::UP
515
+ temp = '</5>Search Up : <!5>'
516
+ else
517
+ temp = '</5>Search Down: <!5>'
518
+ end
519
+
520
+ # Pop up the entry field.
521
+ get_pattern = CDK::ENTRY.new(screen, CDK::CENTER, CDK::CENTER,
522
+ '', label, Curses.color_pair(5) | Curses::A_BOLD,
523
+ '.' | Curses.color_pair(5) | Curses::A_BOLD,
524
+ :MIXED, 10, 0, 256, true, false)
525
+
526
+ # Is there an old search pattern?
527
+ if @search_pattern.size != 0
528
+ get_pattern.set(@search_pattern, get_pattern.min, get_pattern.max,
529
+ get_pattern.box)
530
+ end
531
+
532
+ # Activate this baby.
533
+ list = get_pattern.activate([])
534
+
535
+ # Save teh list.
536
+ if list.size != 0
537
+ @search_pattern = list
538
+ end
539
+
540
+ # Clean up.
541
+ get_pattern.destroy
542
+ end
543
+
544
+ # This searches for a line containing the word and realigns the value on
545
+ # the screen.
546
+ def searchForWord(pattern, direction)
547
+ found = false
548
+
549
+ # If the pattern is empty then return.
550
+ if pattern.size != 0
551
+ if direction == CDK::VIEWER::DOWN
552
+ # Start looking from 'here' down.
553
+ x = @current_top + 1
554
+ while !found && x < @list_size
555
+ pos = 0
556
+ y = 0
557
+ while y < @list[x].size
558
+ plain_char = CDK.CharOf(@list[x][y])
559
+
560
+ pos += 1
561
+ if @CDK.CharOf(pattern[pos-1]) != plain_char
562
+ y -= (pos - 1)
563
+ pos = 0
564
+ elsif pos == pattern.size
565
+ @current_top = [x, @max_top_line].min
566
+ @left_char = if y < @box_width then 0 else @max_left_char end
567
+ found = true
568
+ break
569
+ end
570
+ y += 1
571
+ end
572
+ x += 1
573
+ end
574
+ else
575
+ # Start looking from 'here' up.
576
+ x = @current_top - 1
577
+ while ! found && x >= 0
578
+ y = 0
579
+ pos = 0
580
+ while y < @list[x].size
581
+ plain_char = CDK.CharOf(@list[x][y])
582
+
583
+ pos += 1
584
+ if CDK.CharOf(pattern[pos-1]) != plain_char
585
+ y -= (pos - 1)
586
+ pos = 0
587
+ elsif pos == pattern.size
588
+ @current_top = x
589
+ @left_char = if y < @box_width then 0 else @max_left_char end
590
+ found = true
591
+ break
592
+ end
593
+ end
594
+ end
595
+ end
596
+ end
597
+ return found
598
+ end
599
+
600
+ # This allows us to 'jump' to a given line in the file.
601
+ def jumpToLine
602
+ newline = CDK::SCALE.new(@screen, CDK::CENTER, CDK::CENTER,
603
+ '<C>Jump To Line', '</5>Line :', Curses::A_BOLD,
604
+ @list_size.size + 1, @current_top + 1, 0, @max_top_line + 1,
605
+ 1, 10, true, true)
606
+ line = newline.activate([])
607
+ newline.destroy
608
+ return line - 1
609
+ end
610
+
611
+ # This pops a little message up on the screen.
612
+ def popUpLabel(mesg)
613
+ # Set up variables.
614
+ label = CDK::LABEL.new(@screen, CDK::CENTER, CDK::CENTER,
615
+ mesg, mesg.size, true, false)
616
+
617
+ # Draw the label and wait.
618
+ label.draw(true)
619
+ label.getch([])
620
+
621
+ # Clean up.
622
+ label.destroy
623
+ end
624
+
625
+ # This moves the viewer field to the given location.
626
+ # Inherited
627
+ # def move(xplace, yplace, relative, refresh_flag)
628
+ # end
629
+
630
+ # This function draws the viewer widget.
631
+ def draw(box)
632
+ # Do we need to draw in the shadow?
633
+ unless @shadow_win.nil?
634
+ Draw.drawShadow(@shadow_win)
635
+ end
636
+
637
+ # Box it if it was asked for.
638
+ if box
639
+ Draw.drawObjBox(@win, self)
640
+ @win.refresh
641
+ end
642
+
643
+ # Draw the info in the viewer.
644
+ self.drawInfo
645
+ end
646
+
647
+ # This redraws the viewer buttons.
648
+ def drawButtons
649
+ # No buttons, no drawing
650
+ if @button_count == 0
651
+ return
652
+ end
653
+
654
+ # Redraw the buttons.
655
+ (0...@button_count).each do |x|
656
+ Draw.writeChtype(@win, @button_pos[x], @box_height - 2,
657
+ @button[x], CDK::HORIZONTAL, 0, @button_len[x])
658
+ end
659
+
660
+ # Highlight the current button.
661
+ (0...@button_len[@current_button]).each do |x|
662
+ # Strip the character of any extra attributes.
663
+ character = CDK.CharOf(@button[@current_button][x])
664
+
665
+ # Add the character into the window.
666
+ @win.mvwaddch(@box_height - 2, @button_pos[@current_button] + x,
667
+ character.ord | @button_highlight)
668
+ end
669
+
670
+ # Refresh the window.
671
+ @win.refresh
672
+ end
673
+
674
+ # This sets the background attribute of the widget.
675
+ def setBKattr(attrib)
676
+ @win.wbkgd(attrib)
677
+ end
678
+
679
+ def destroyInfo
680
+ @list = []
681
+ @list_pos = []
682
+ @list_len = []
683
+ end
684
+
685
+ # This function destroys the viewer widget.
686
+ def destroy
687
+ self.destroyInfo
688
+
689
+ self.cleanTitle
690
+
691
+ # Clean up the windows.
692
+ CDK.deleteCursesWindow(@shadow_win)
693
+ CDK.deleteCursesWindow(@win)
694
+
695
+ # Clean the key bindings.
696
+ self.cleanBindings(:VIEWER)
697
+
698
+ # Unregister this object.
699
+ CDK::SCREEN.unregister(:VIEWER, self)
700
+ end
701
+
702
+ # This function erases the viewer widget from the screen.
703
+ def erase
704
+ if self.validCDKObject
705
+ CDK.eraseCursesWindow(@win)
706
+ CDK.eraseCursesWindow(@shadow_win)
707
+ end
708
+ end
709
+
710
+ # This draws the viewer info lines.
711
+ def drawInfo
712
+ temp = ''
713
+ line_adjust = false
714
+
715
+ # Clear the window.
716
+ @win.erase
717
+
718
+ self.drawTitle(@win)
719
+
720
+ # Draw in the current line at the top.
721
+ if @show_line_info == true
722
+ # Set up the info line and draw it.
723
+ if @in_progress
724
+ temp = 'processing...'
725
+ elsif @list_size != 0
726
+ temp = '%d/%d %2.0f%%' % [@current_top + 1, @list_size,
727
+ ((1.0 * @current_top + 1) / (@list_size)) * 100]
728
+ else
729
+ temp = '%d/%d %2.0f%%' % [0, 0, 0.0]
730
+ end
731
+
732
+ # The list_adjust variable tells us if we have to shift down one line
733
+ # because the person asked for the line X of Y line at the top of the
734
+ # screen. We only want to set this to true if they asked for the info
735
+ # line and there is no title or if the two items overlap.
736
+ if @title_lines == '' || @title_pos[0] < temp.size + 2
737
+ list_adjust = true
738
+ end
739
+ Draw.writeChar(@win, 1,
740
+ if list_adjust then @title_lines else 0 end + 1,
741
+ temp, CDK::HORIZONTAL, 0, temp.size)
742
+ end
743
+
744
+ # Determine the last line to draw.
745
+ last_line = [@list_size, @view_size].min
746
+ last_line -= if list_adjust then 1 else 0 end
747
+
748
+ # Redraw the list.
749
+ (0...last_line).each do |x|
750
+ if @current_top + x < @list_size
751
+ screen_pos = @list_pos[@current_top + x] + 1 - @left_char
752
+
753
+ Draw.writeChtype(@win,
754
+ if screen_pos >= 0 then screen_pos else 1 end,
755
+ x + @title_lines + if list_adjust then 1 else 0 end + 1,
756
+ @list[x + @current_top], CDK::HORIZONTAL,
757
+ if screen_pos >= 0
758
+ then 0
759
+ else @left_char - @list_pos[@current_top + x]
760
+ end,
761
+ @list_len[x + @current_top])
762
+ end
763
+ end
764
+
765
+ # Box it if we have to.
766
+ if @box
767
+ Draw.drawObjBox(@win, self)
768
+ @win.refresh
769
+ end
770
+
771
+ # Draw the separation line.
772
+ if @button_count > 0
773
+ boxattr = @BXAttr
774
+
775
+ (1..@box_width).each do |x|
776
+ @win.mvwaddch(@box_height - 3, x, @HZChar | boxattr)
777
+ end
778
+
779
+ @win.mvwaddch(@box_height - 3, 0, CDK::ACS_LTEE | boxattr)
780
+ @win.mvwaddch(@box_height - 3, @win.maxx - 1,
781
+ CDK::ACS_RTEE | boxattr)
782
+ end
783
+
784
+ # Draw the buttons. This will call refresh on the viewer win.
785
+ self.drawButtons
786
+ end
787
+
788
+ # The list_size may be negative, to assign no definite limit.
789
+ def createList(list_size)
790
+ status = false
791
+
792
+ self.destroyInfo
793
+
794
+ if list_size >= 0
795
+ status = true
796
+
797
+ @list = []
798
+ @list_pos = []
799
+ @list_len = []
800
+ end
801
+ return status
802
+ end
803
+
804
+ def position
805
+ super(@win)
806
+ end
807
+
808
+ def object_type
809
+ :VIEWER
810
+ end
811
+ end
812
+ end