1
2 // ------------------------------------------------------------------
3 // GoldED+
4 // Copyright (C) 1990-1999 Odinn Sorensen
5 // Copyright (C) 1999-2000 Alexander S. Aganichev
6 // ------------------------------------------------------------------
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 // MA 02111-1307 USA
21 // ------------------------------------------------------------------
22 // $Id: gearea.cpp,v 1.14 2011/02/22 23:51:03 stas_degteff Exp $
23 // ------------------------------------------------------------------
24 // Arealister and other area-specific code
25 // ------------------------------------------------------------------
26
27 #include <golded.h>
28 #include <gutlos.h>
29
30
31 // ------------------------------------------------------------------
32
33 extern int arealistnumgrps;
34
35 bool in_arealist = false;
36
37 GPickArealist* PickArealist;
38
39 Echo area_maybe;
40 int areaswithgroupid = 0;
41 uint* areanumbers = NULL;
42
43 // 111111111122222222223333333333444444444455555555556666666666777777777
44 // 0123456789012345678901234567890123456789012345678901234567890123456789012345678
45 // ��Area�Description�������������������������Msgs���New��EchoID��������������GrpĿ
46 // � 1> NET FidoNet Z3/4/5/6 118+ 3* NET.FIDOZX A �
47
48 // AREALISTFORMAT "AM D CPUN E G"
49
50 int area_pos = -1;
51 int area_width = 4;
52 int marked_pos = -1;
53 int marked_width = 1;
54 const char marked_char = MMRK_MARK;
55 int desc_pos = -1;
56 int desc_width = -1;
57 int count_pos = -1;
58 int count_width = 6;
59 int pmark_pos = -1;
60 int pmark_width = 1;
61 const char pmark_char = '+';
62 int unread_pos = -1;
63 int unread_width = 6;
64 int changed_pos = -1;
65 int changed_width = 1;
66 const char changed_char = '*';
67 int echoid_pos = -1;
68 int echoid_width = 0;
69 int groupid_pos = -1;
70 int groupid_width = 0;
71
72
73 // ------------------------------------------------------------------
74
GPickArealist()75 GPickArealist::GPickArealist() {
76
77 areawin1 = 0;
78 areawin2 = 0;
79 tempwin1 = 0;
80 tempwin2 = 0;
81
82 pmails = 0;
83 pmareas = 0;
84 pmscan = false;
85
86 area_fuzidx = 0;
87
88 }
89
90
91 // ------------------------------------------------------------------
92
AreasRenumber()93 void GPickArealist::AreasRenumber() {
94
95 for(int n=0,a=1,t=AL.size(); n<t; n++)
96 areanumbers[n] = AL[n]->isseparator() ? 0 : a++;
97 }
98
99
100 // ------------------------------------------------------------------
101
is_selectable(uint idx)102 bool GPickArealist::is_selectable(uint idx) {
103
104 Area* area = AL.AreaNoToPtr(idx);
105 return (not area->isseparator());
106
107 }
108
109
110 // ------------------------------------------------------------------
111
do_delayed()112 void GPickArealist::do_delayed() {
113
114 Area* area = AL.AreaNoToPtr(index);
115
116 const size_t buflen=strlen(title)+strlen(area_maybe);
117 const size_t tmplen=(buflen>MAXCOL?buflen:MAXCOL);
118 char * buf = new char[buflen+3];
119 buf[buflen] = '\0';
120 buf[buflen+1] = '\xFF';
121 buf[buflen+2] = '\0';
122 char * tmp = new char[tmplen+3];
123 tmp[tmplen] = '\0';
124 tmp[tmplen+1] = '\xFF';
125 tmp[tmplen+2] = '\0';
126
127 update_statuslinef("%s: %u %s, %u %s, %u %s", "", area->echoid(), area->Msgn.Count(),
128 (area->Msgn.Count() == 1 ? LNG->msg : LNG->msgs), area->unread,
129 LNG->unread, area->PMrk.Count(), LNG->personal);
130
131 strcpy(stpcpy(buf, title), area_maybe);
132 strsetsz(strcpy(tmp, buf), MAXCOL);
133 wwprintstr(tempwin, 0, 0, wattr, tmp);
134
135 if(CFG->switches.get(arealistpagebar))
136 wscrollbar(W_VERT, maximum_index+1, maximum_index, index);
137
138 if (buf[buflen] || buf[buflen+1]!='\xFF' || buf[buflen+2])
139 {
140 LOG.errpointer(__FILE__,__LINE__);
141 LOG.printf("! Buffer overflow: buf in GPickArealist::do_delayed(), 8 or 9 lines above");
142 PointerErrorExit();
143 }
144 if (tmp[tmplen] || tmp[tmplen+1]!='\xFF' || tmp[tmplen+2])
145 {
146 LOG.errpointer(__FILE__,__LINE__);
147 LOG.printf("! Buffer overflow: tmp in GPickArealist::do_delayed(), 15 or 16 lines above");
148 PointerErrorExit();
149 }
150 delete buf;
151 delete tmp;
152 }
153
154
155 // ------------------------------------------------------------------
156
close_all()157 void GPickArealist::close_all() {
158
159 if(areawin1)
160 wunlink(areawin1);
161 if(areawin2)
162 wunlink(areawin2);
163 if(tempwin1)
164 wunlink(tempwin1);
165 if(tempwin2)
166 wunlink(tempwin2);
167 }
168
169
170 // ------------------------------------------------------------------
171
dispbuf(char * buf,int areano)172 void GPickArealist::dispbuf(char* buf, int areano) {
173
174 Area* area = AL.AreaNoToPtr(areano);
175
176 memset(buf, ' ', MAXCOL-2);
177 buf[MAXCOL-2] = NUL;
178
179 char areabuf[33];
180 gsprintf(PRINTF_DECLARE_BUFFER(areabuf), "%u", CFG->switches.get(arealistnos) ? area->board() : areanumbers[areano]);
181 int areawidth = strlen(areabuf);
182
183 char markedbuf[2] = { " " };
184 *markedbuf = area->ismarked() ? marked_char : ' ';
185 int markedwidth = 1;
186
187 char descbuf[100];
188 int descwidth = strlen(strcpy(descbuf, area->desc()));
189
190 char countbuf[33];
191 if (area->isscanned)
192 gsprintf(PRINTF_DECLARE_BUFFER(countbuf), "%u", (uint)area->Msgn.Count());
193 else
194 strcpy(countbuf, "-");
195 int countwidth = strlen(countbuf);
196
197 char pmarkbuf[2] = { " " };
198 *pmarkbuf = area->PMrk.Count() ? pmark_char : ' ';
199 int pmarkwidth = 1;
200
201 char unreadbuf[33];
202 if (area->isscanned)
203 gsprintf(PRINTF_DECLARE_BUFFER(unreadbuf), "%u", (uint)((CFG->arealisttype == AL_TOTNEW) ? area->unread : area->lastread()));
204 else
205 strcpy(unreadbuf, "-");
206 int unreadwidth = strlen(unreadbuf);
207
208 char changedbuf[2] = { " " };
209 *changedbuf = area->isunreadchg ? changed_char : ' ';
210 int changedwidth = 1;
211
212 char echoidbuf[100];
213 int echoidwidth = strlen(strcpy(echoidbuf, area->echoid()));
214
215 char groupidbuf[10] = { "" };
216 if (groupid_width)
217 {
218 if (area->groupid() & 0x8000u)
219 {
220 if (groupid_width > 2)
221 gsprintf(PRINTF_DECLARE_BUFFER(groupidbuf), "%u", area->groupid()&0x7FFF);
222 }
223 else if (g_isupper(area->groupid()))
224 gsprintf(PRINTF_DECLARE_BUFFER(groupidbuf), "%c", (char)area->groupid());
225 }
226 int groupidwidth = strlen(groupidbuf);
227
228 areawidth = MinV(areawidth, area_width);
229 markedwidth = MinV(markedwidth, marked_width);
230 descwidth = MinV(descwidth, desc_width);
231 countwidth = MinV(countwidth, count_width);
232 pmarkwidth = MinV(pmarkwidth, pmark_width);
233 unreadwidth = MinV(unreadwidth, unread_width);
234 changedwidth = MinV(changedwidth, changed_width);
235 echoidwidth = MinV(echoidwidth, echoid_width);
236 groupidwidth = MinV(groupidwidth, groupid_width);
237
238 memcpy(buf+area_pos+area_width-areawidth, areabuf, areawidth);
239 memcpy(buf+marked_pos, markedbuf, markedwidth);
240 memcpy(buf+desc_pos, descbuf, descwidth);
241 memcpy(buf+count_pos+count_width-countwidth, countbuf, countwidth);
242 memcpy(buf+pmark_pos, pmarkbuf, pmarkwidth);
243 memcpy(buf+unread_pos+unread_width-unreadwidth, unreadbuf, unreadwidth);
244 memcpy(buf+changed_pos, changedbuf, changedwidth);
245 memcpy(buf+echoid_pos, echoidbuf, echoidwidth);
246 memcpy(buf+groupid_pos+groupid_width-groupidwidth, groupidbuf, groupidwidth);
247 }
248
249 // ------------------------------------------------------------------
250
center()251 void GPickArealist::center() {
252
253 uint room, toproom, botroom;
254
255 toproom = index;
256 botroom = maximum_index - index;
257 if(toproom > maximum_position/2) {
258 if(botroom > maximum_position/2)
259 room = maximum_position/2;
260 else if(botroom)
261 room = maximum_position - botroom;
262 else
263 room = maximum_position;
264 }
265 else
266 room = toproom;
267
268 position = room;
269 display_page();
270 }
271
272
273 // ------------------------------------------------------------------
274
jump_to()275 void GPickArealist::jump_to() {
276
277 uint n = index+1;
278 bool found = false;
279 // Search for next marked area, wrapping 'round if needed
280 for(; n<=maximum_index; n++) {
281 if(not AL[n]->isseparator() and AL[n]->ismarked()) {
282 found = true;
283 break;
284 }
285 }
286
287 if(not found) {
288 for(n = minimum_index; n <= index; n++) {
289 if(not AL[n]->isseparator() and AL[n]->ismarked())
290 break;
291 }
292 }
293
294 if(n > maximum_index)
295 n = minimum_index;
296
297 while(AL[n]->isseparator()) {
298 if((++n) > maximum_index)
299 n = minimum_index;
300 }
301
302 index = n;
303 center();
304 }
305
306
307 // ------------------------------------------------------------------
308
jumpmatch()309 void GPickArealist::jumpmatch() {
310
311 uint n = index+1;
312 bool found = false;
313 // Search for next marked area, wrapping 'round if needed
314 for(; n<=maximum_index; n++) {
315 if(not AL[n]->isseparator() and (strnieql(area_maybe, AL[n]->echoid(), area_fuzidx) or striinc(area_maybe, AL[n]->echoid()))) {
316 found = true;
317 break;
318 }
319 }
320
321 if(not found) {
322 for(n = minimum_index; n <= index; n++) {
323 if(not AL[n]->isseparator() and (strnieql(area_maybe, AL[n]->echoid(), area_fuzidx) or striinc(area_maybe, AL[n]->echoid())))
324 break;
325 }
326 }
327
328 if(n > maximum_index)
329 n = minimum_index;
330
331 while(AL[n]->isseparator()) {
332 if((++n) > maximum_index)
333 n = minimum_index;
334 }
335
336 index = n;
337 center();
338
339 }
340
341
342 // ------------------------------------------------------------------
343
open()344 void GPickArealist::open() {
345
346 int active=NO;
347
348 #if defined(GUTLOS_FUNCS)
349 g_set_ostitle_name("Arealist",0);
350 #endif
351
352 if(ypos) {
353 if(tempwin1) {
354 tempwin = tempwin1;
355 areawin = areawin1;
356 active = YES;
357 }
358 }
359 else {
360 if(tempwin2) {
361 tempwin = tempwin2;
362 areawin = areawin2;
363 active = YES;
364 }
365 }
366
367 if(active) {
368 wunhide(tempwin);
369 wprints(0,0, wattr, title);
370 wunhide(areawin);
371 }
372 else {
373 tempwin = wopen_(ypos, xpos, 1, MAXCOL, 5, battr, wattr, sbattr);
374 wprints(0,0, wattr, title);
375 areawin = wopen_(ypos+1, xpos, ylen+2, MAXCOL, btype, battr, wattr, sbattr);
376
377 if(ypos) {
378 tempwin1 = tempwin;
379 areawin1 = areawin;
380 }
381 else {
382 tempwin2 = tempwin;
383 areawin2 = areawin;
384 }
385
386 if(area_width)
387 wmessage(LNG->Area, TP_BORD, 1+area_pos+(marked_pos==area_pos+area_width?1:0), tattr);
388 if(desc_width)
389 wmessage(LNG->Description, TP_BORD, 1+desc_pos, tattr);
390 if(count_width)
391 wmessage(LNG->Msgs, TP_BORD, 1+count_pos+count_width-strlen(LNG->Msgs), tattr);
392 if(unread_width) {
393 if(CFG->arealisttype == AL_TOTLST)
394 wmessage(LNG->Last, TP_BORD, 1+unread_pos+unread_width-strlen(LNG->Last), tattr);
395 else if(CFG->arealisttype == AL_TOTNEW)
396 wmessage(LNG->New, TP_BORD, 1+unread_pos+unread_width-strlen(LNG->New), tattr);
397 }
398 if(echoid_width)
399 wmessage(LNG->EchoID, TP_BORD, 1+echoid_pos, tattr);
400 if(groupid_width) {
401 char grpbuf[40];
402 if(groupid_width > 2)
403 strcpy(grpbuf, LNG->Grp);
404 else {
405 *grpbuf = *(LNG->Grp);
406 grpbuf[1] = NUL;
407 }
408 wmessage(grpbuf, TP_BORD, 1+groupid_pos, tattr);
409 }
410
411 }
412 if(CFG->switches.get(areaautonext) and ypos == 0 and index >= minimum_index and not AL[index]->ismarked()) {
413 jump_to();
414 }
415 else
416 center();
417 }
418
419
420 // ------------------------------------------------------------------
421
close()422 void GPickArealist::close() {
423
424 whide();
425 whide();
426 }
427
428 // ------------------------------------------------------------------
429
precursor()430 void GPickArealist::precursor() {
431
432 *area_maybe = 0;
433 area_fuzidx = 0;
434 }
435
436
437 // ------------------------------------------------------------------
438
print_line(uint idx,uint pos,bool isbar)439 void GPickArealist::print_line(uint idx, uint pos, bool isbar) {
440
441 vchar vbuf[256];
442 char buf[256];
443
444 if(AL[idx]->isseparator()) {
445 Area* area = AL.AreaNoToPtr(idx);
446
447 int sep_pos = (desc_pos != -1) ? desc_pos : echoid_pos;
448
449 {for(int c = 0; c < sep_pos; c++)
450 vbuf[c] = _box_table(btype, 1);}
451 vbuf[sep_pos] = NUL;
452 wprintvs(pos, 0, battr|ACSET, vbuf);
453 wprints(pos, sep_pos, tattr, area->desc());
454
455 int l = strlen(area->desc());
456 int n = MAXCOL-2-sep_pos-l;
457
458 {for(int c = 0; c < n; c++)
459 vbuf[c] = _box_table(btype,1);}
460 vbuf[n] = NUL;
461 wprintvs(pos, sep_pos+l, battr|ACSET, vbuf);
462 }
463 else {
464 dispbuf(buf, idx);
465 wprints(pos, 0, isbar ? sattr : wattr, buf);
466 if(AL[idx]->ismarked())
467 wprintc(pos, marked_pos, isbar ? sattr : hattr, marked_char);
468 }
469
470 }
471
472
473 // ------------------------------------------------------------------
474
AreaCatchUp(uint n)475 void GPickArealist::AreaCatchUp(uint n) {
476
477 // Do not do catch up if there's active area
478 if(AA->isopen())
479 return;
480
481 GMenuAreaCatchup MenuAreaCatchup;
482 GMsg* msg = (GMsg*)throw_calloc(1, sizeof(GMsg));
483
484 int mode = MenuAreaCatchup.Run();
485
486 if(mode != SCAN_QUIT) {
487 for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) {
488
489 if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[n])) {
490
491 if((*AL.item)->isseparator())
492 continue;
493
494 update_statuslinef("%s ...", "", (*AL.item)->echoid());
495
496 AA = (*AL.item);
497 AA->Open();
498
499 if(CFG->switches.get(highlightunread) and CFG->switches.get(areacatchupread)) {
500 w_info(LNG->Wait);
501 for(uint i=AA->lastread()+1; i <= AA->Msgn.Count(); i++) {
502 AA->LoadHdr(msg, AA->Msgn.CvtReln(i), false);
503 if(msg->timesread++ == 0)
504 AA->UpdateTimesread(msg);
505 }
506 w_info(NULL);
507 }
508
509 AA->set_lastread(AA->Msgn.Count());
510 AA->isvalidchg = false;
511 AA->Close();
512 }
513 }
514 }
515 throw_free(msg);
516 }
517
518
519 // ------------------------------------------------------------------
520
AreaDropMsgMarks(uint n)521 void GPickArealist::AreaDropMsgMarks(uint n) {
522
523 GMenuAreaDropMarks MenuAreaDropMarks;
524
525 uint nummarks = 0;
526
527 for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++)
528 nummarks += (*AL.item)->Mark.Count();
529
530 char buf[256];
531 gsprintf(PRINTF_DECLARE_BUFFER(buf), LNG->DropMarksInfo, longdotstr(nummarks));
532
533 w_info(buf);
534 int mode = MenuAreaDropMarks.Run();
535 w_info(NULL);
536
537 if(mode != SCAN_QUIT) {
538 for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) {
539 if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[n])) {
540
541 if((*AL.item)->isseparator())
542 continue;
543
544 (*AL.item)->Mark.ResetAll();
545 }
546 }
547 }
548 }
549
550
551 // ------------------------------------------------------------------
552
handle_key()553 bool GPickArealist::handle_key() {
554
555 uint n;
556 uint x;
557 const char* adesc;
558 char buf[256], tmp[256];
559
560 int mode, changed, currno;
561
562 gkey kk;
563
564 if(key < KK_Commands) {
565 key = key_tolower(key);
566 if((key == Key_Esc) and esc_abort)
567 key = KK_AreaAbort;
568 else {
569 kk = SearchKey(key, AreaKey, AreaKeys);
570 if(kk)
571 key = kk;
572 }
573 }
574
575
576 switch(key) {
577
578 case KK_AreaDropMsgMarks:
579 AreaDropMsgMarks(index);
580 break;
581
582 case KK_AreaSelectMarks:
583 AL.Select_Mask();
584 break;
585
586 case KK_AreaAskExit:
587 {
588 GMenuQuit MenuQuit;
589 aborted = gkbd.quitall = (MenuQuit.Run()!=0);
590 if(gkbd.quitall) {
591 precursor();
592 return false;
593 }
594 }
595 break;
596
597 case KK_AreaAbort:
598 aborted = true;
599 // Drop Through
600
601 case KK_AreaSelect:
602 if(AL[index]->isseparator()) {
603 if(not PlayMacro(key, KT_A))
604 SayBibi();
605 break;
606 }
607 precursor();
608 return false;
609
610 case KK_AreaQuitNow:
611 aborted = gkbd.quitall = true;
612 precursor();
613 return false;
614
615 case KK_AreaToggle:
616 AL[index]->set_marked(not AL[index]->ismarked());
617 display_bar();
618 precursor();
619 cursor_down();
620 break;
621
622 case KK_AreaMark:
623 AL[index]->set_marked(true);
624 display_bar();
625 precursor();
626 cursor_down();
627 break;
628
629 case KK_AreaUnmark:
630 AL[index]->set_marked(false);
631 display_bar();
632 precursor();
633 cursor_down();
634 break;
635
636 case KK_AreaBoardnos:
637 CFG->switches.set(arealistnos, not CFG->switches.get(arealistnos));
638 update();
639 break;
640
641 case KK_AreaCatchUp:
642 AreaCatchUp(index);
643 update();
644 break;
645
646 case KK_AreaJumpNextMatch:
647 jumpmatch();
648 break;
649
650 case KK_AreaJump:
651 {
652 precursor();
653 jump_to();
654 }
655 break;
656
657 case KK_AreaDosShell:
658 DosShell();
659 break;
660
661 case KK_AreaGotoPrev: precursor(); cursor_up(); break;
662 case KK_AreaGotoNext: precursor(); cursor_down(); break;
663 case KK_AreaGotoFirst: precursor(); cursor_first(); break;
664 case KK_AreaGotoLast: precursor(); cursor_last(); break;
665
666 case KK_AreaSoundkill:
667 HandleGEvent(EVTT_STOPVOICE);
668 break;
669
670 case KK_AreaTouchNetscan:
671 TouchNetscan();
672 break;
673
674 case KK_AreaHeat:
675 {
676 GMenuAreaHeat MenuAreaHeat;
677 mode = MenuAreaHeat.Run();
678 if(mode != SCAN_QUIT) {
679 for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) {
680 if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[index-1])) {
681 update_statuslinef("%s %s", "", 1+LNG->ScanningArea, (*AL.item)->echoid());
682 (*AL.item)->SetHighwaterMark();
683 }
684 }
685 }
686 }
687 break;
688
689 case KK_AreaZap:
690 {
691 GMenuAreaZap MenuAreaZap;
692 mode = MenuAreaZap.Run();
693 if(mode != SCAN_QUIT) {
694 for(AL.item = AL.idx.begin(); AL.item != AL.idx.end(); AL.item++) {
695 if((mode == SCAN_MARKED and (*AL.item)->ismarked()) or mode == SCAN_ALL or (mode == SCAN_CURRENT and (*AL.item) == AL[index-1])) {
696 update_statuslinef("%s %s", "", 1+LNG->ScanningArea, (*AL.item)->echoid());
697 (*AL.item)->ResetHighwaterMark();
698 }
699 }
700 }
701 }
702 break;
703
704 case KK_AreaScanPM:
705 pmscan = true;
706 pmails = 0;
707 pmareas = 0;
708 // DROP THROUGH //
709
710 case KK_AreaScan:
711 {
712 currno = index;
713 GMenuAreaScan MenuAreaScan;
714 mode = MenuAreaScan.Run(pmscan);
715 if(mode != SCAN_QUIT) {
716
717 w_info(LNG->Wait);
718
719 strcpy(stecho, AL[index]->echoid());
720
721 if(mode == SCAN_IMPORTQWK)
722 changed = ImportQWK();
723 else if(mode == SCAN_EXPORTQWK)
724 changed = ExportQWK();
725 else if(mode == SCAN_IMPORTSOUP)
726 changed = ImportSOUP();
727 else if(mode == SCAN_EXPORTSOUP)
728 changed = ExportSOUP();
729 else {
730 if(cmdlinedebughg)
731 LOG.printf("- AreaScan from arealist");
732 changed = AL.AreaScan(mode, currno, pmscan, pmails, pmareas);
733 }
734
735 w_info();
736
737 AL.SetActiveAreaNo(currno);
738 if(changed) {
739 AL.Sort();
740 AreasRenumber();
741 index = AL.AreaEchoToNo(stecho);
742 center();
743 }
744
745 if(pmscan) {
746 if(pmails) {
747 w_infof(LNG->FoundPersonal,
748 pmails, (pmails==1?"":"s"),
749 pmareas, (pmareas==1?"":"s")
750 );
751 }
752 else {
753 w_info(LNG->NoPersonal);
754 }
755 waitkeyt(10000);
756 w_info();
757 }
758 }
759 pmscan = false;
760 }
761 break;
762
763 case Key_Tick:
764 CheckTick(KK_AreaQuitNow);
765 break;
766
767 case KK_AreaUndefine:
768 break;
769
770 case KK_AreaWriteGoldlast:
771 w_info(LNG->Wait);
772 AL.WriteGoldLast();
773 w_info();
774 break;
775
776 default:
777 if(key < KK_Macro) {
778 n = g_toupper(key & 0xFF);
779 if((area_fuzidx < area_maxfuz) or (key == Key_BS)) {
780
781 // Incremental search in the echoids
782 if(not iscntrl(n) or (key == Key_BS)) {
783 if(n == ' ')
784 n = '_';
785 if(key != Key_BS)
786 area_maybe[area_fuzidx++] = (char)n;
787 else if(area_fuzidx)
788 area_fuzidx--;
789 area_maybe[area_fuzidx] = NUL;
790 strcpy(stpcpy(buf, title), area_maybe);
791 strsetsz(strcpy(tmp, buf), MAXCOL);
792 wwprintstr(tempwin, 0, 0, wattr, tmp);
793 if(area_fuzidx) {
794
795 x = atoi(area_maybe);
796 if(x) {
797 if(CFG->switches.get(arealistnos) and (isdigit(area_maybe[1]) or (area_maybe[1] == NUL))) {
798 for(n=0; n<AL.size(); n++) {
799 if(AL[n]->board() == x) {
800 x = n;
801 goto RedrawAreas;
802 }
803 }
804 x = 0; // No match found
805 }
806 else {
807 for(n=0; n<area_fuzidx; n++) {
808 if(not isdigit(area_maybe[n])) {
809 x = 0;
810 break;
811 }
812 }
813 }
814 }
815
816 if(x >= 1 and x<=AL.size()) {
817 {
818 for(int a=0, at=AL.size(); a<at; a++) {
819 if(areanumbers[a] == x) {
820 x = a;
821 goto RedrawAreas;
822 }
823 }
824 }
825 x = (uint)-1;
826
827 RedrawAreas:
828
829 if(x == (uint)-1)
830 x = index;
831 while(AL[x]->isseparator()) {
832 x++;
833 if(x > maximum_index)
834 x = minimum_index;
835 }
836 if(x != index)
837 display_line();
838 #define _topidx (index-position) // Shorthand..
839 #define _botidx (index+(maximum_position-position)) // Shorthand..
840 if((_topidx <= x) and (x <= _botidx)) {
841 position += (x-index);
842 index = x;
843 display_page(); /////////// NEW
844 }
845 else {
846 index = x;
847 center();
848 }
849 break;
850 }
851 else {
852 // Regular search
853 for(n=0; n<AL.size(); n++) {
854 adesc = AL[n]->echoid();
855 if(strnicmp(area_maybe, adesc, area_fuzidx) == 0) {
856 AL.Sort();
857 AreasRenumber();
858 x = AL.AreaEchoToNo(adesc);
859 goto RedrawAreas;
860 }
861 }
862 // Search inside
863 for(n=0; n<AL.size(); n++) {
864 adesc = AL[n]->echoid();
865 if(striinc(area_maybe, adesc)) {
866 AL.Sort();
867 AreasRenumber();
868 x = AL.AreaEchoToNo(adesc);
869 goto RedrawAreas;
870 }
871 }
872 }
873 }
874 else {
875 adesc = AL[index]->echoid();
876 AL.Sort();
877 AreasRenumber();
878 index = AL.AreaEchoToNo(adesc);
879 center();
880 }
881 break;
882 }
883 }
884 }
885 if(not PlayMacro(key, KT_A))
886 SayBibi();
887 }
888
889 return true;
890 }
891
892 // ------------------------------------------------------------------
893
Run(const char * _title,int wpos,int & idx)894 int GPickArealist::Run(const char* _title, int wpos, int& idx) {
895
896 HandleGEvent(EVTT_AREALIST);
897
898 xpos = 0; // Window starting coloumn
899 ypos = wpos; // Window starting row
900 xlen = MAXCOL-2; // Window ending coloumn
901 ylen = MAXROW-wpos-4; // Window ending row
902 title = _title; // Window title
903 btype = W_BAREA; // Window border type
904 battr = C_AREAB; // Window border attributes
905 wattr = C_AREAW; // Window Color
906 tattr = C_AREAT; // Window Title Color
907 sattr = C_AREAS; // Window Selection Bar Color
908 hattr = C_AREAQ; // Window Highlight Color
909 sbattr = C_AREAPB; // Window Scrollbar Color
910 helpcat = H_Area; // Window Help Category
911
912 maximum_index = AL.size() - 1; // List Entries - 1
913 maximum_position = MinV((size_t)ylen-1, AL.size()-1); // Display Pos
914 index = AL.AreaIdToNo(idx); // List Index
915 listwrap = CFG->switches.get(displistwrap); // True if wrap-around is supported
916 esc_abort = (wpos!=0);
917 area_maxfuz = MinV(sizeof(Echo), MAXCOL-strlen(title)-1);
918
919 goldmark = ' ';
920
921 areanumbers = (uint*)throw_calloc(AL.size(), sizeof(uint));
922 AreasRenumber();
923
924 run_picker();
925
926 throw_release(areanumbers);
927
928 if(not aborted)
929 return AL[index]->areaid();
930
931 idx = AL[index]->areaid();
932
933 return -1;
934 }
935
936
937 // ------------------------------------------------------------------
938
AreaPick(char * title,int wpos,int * idx)939 int AreaPick(char* title, int wpos, int* idx) {
940
941 GPickArealist p;
942 int new_area;
943
944 if(gkbd.quitall)
945 return -1;
946
947 PickArealist = &p;
948
949 in_arealist = true;
950 new_area = p.Run(title, wpos, *idx);
951 in_arealist = false;
952
953 PickArealist = NULL;
954
955 return new_area;
956 }
957
958
959 // ------------------------------------------------------------------
960
961