Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / utilities / More / more.c
blob37be7aa170353cd75d002427cd60c7b1f927a74d
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <exec/memory.h>
9 #include <dos/dos.h>
10 #include <intuition/intuition.h>
11 #include <intuition/imageclass.h>
12 #include <intuition/gadgetclass.h>
13 #include <libraries/locale.h>
14 #include <libraries/gadtools.h>
15 #include <devices/rawkeycodes.h>
17 #include <graphics/gfx.h>
18 #include <utility/hooks.h>
19 #include <workbench/startup.h>
21 #include <proto/exec.h>
22 #include <proto/dos.h>
23 #include <proto/intuition.h>
24 #include <proto/graphics.h>
25 #include <proto/gadtools.h>
26 #include <proto/alib.h>
28 #include "global.h"
29 #include "req.h"
31 #define CATCOMP_NUMBERS
32 #include "strings.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
39 #define DEBUG 0
40 #include <aros/debug.h>
42 /****************************************************************************************/
44 /* #define USE_WRITEMASK */
45 #define USE_SIMPLEREFRESH 0
47 #define DEFAULT_TABSIZE 8
49 #define INNER_SPACING_X 2
50 #define INNER_SPACING_Y 2
52 #define MAX_TEXTLINELEN 4096
54 #define ARG_TEMPLATE "FILE"
56 enum
58 ARG_FILE,
59 NUM_ARGS
62 enum
64 GAD_UPARROW,
65 GAD_DOWNARROW,
66 GAD_LEFTARROW,
67 GAD_RIGHTARROW,
68 GAD_VERTSCROLL,
69 GAD_HORIZSCROLL,
70 NUM_GADGETS
73 enum
75 IMG_UPARROW,
76 IMG_DOWNARROW,
77 IMG_LEFTARROW,
78 IMG_RIGHTARROW,
79 IMG_SIZE,
80 NUM_IMAGES
83 /****************************************************************************************/
85 struct LineNode
87 char *text;
88 UWORD stringlen;
89 UWORD textlen;
90 BOOL invert;
93 /****************************************************************************************/
95 struct IntuitionBase *IntuitionBase;
96 struct GfxBase *GfxBase;
97 struct Library *GadToolsBase;
98 struct Screen *scr;
99 struct DrawInfo *dri;
100 APTR vi;
101 struct Menu *menus;
102 struct Window *win;
104 ULONG gotomask, findmask;
105 UBYTE filenamebuffer[300];
107 /****************************************************************************************/
109 static struct RastPort *rp;
110 static struct RDArgs *MyArgs;
112 static struct Gadget *gad[NUM_GADGETS], *firstgadget, *activearrowgad;
113 static struct Image *img[NUM_GADGETS];
115 static struct LineNode *linearray;
117 static UBYTE *filebuffer;
119 static char *filename, *fillename_dest, s[256], *searchtext;
121 static BPTR fh;
123 static UWORD tabsize = DEFAULT_TABSIZE;
125 static WORD fontwidth, fontheight, borderleft, bordertop;
126 static WORD shinepen, shadowpen, bgpen, textpen;
127 static WORD borderright, borderbottom, visiblex, visibley;
128 static WORD fontbaseline, textstartx, textstarty, textendx, textendy;
129 static WORD textwidth, textheight, viewstartx, viewstarty;
130 static WORD winwidth, winheight;
132 static ULONG winmask;
133 static LONG filelen, num_lines, max_textlen;
134 static LONG search_startline, found_line = -1;
135 static WORD arrowticker;
137 static BOOL in_main_loop;
139 static IPTR Args[NUM_ARGS];
141 static BPTR oldlock = (BPTR)-1;
142 static BPTR parentlock = (BPTR)-1;
144 /*********************************************************************************************/
146 WORD ShowMessage(CONST_STRPTR title, CONST_STRPTR text, CONST_STRPTR gadtext)
148 struct EasyStruct es;
150 es.es_StructSize = sizeof(es);
151 es.es_Flags = 0;
152 es.es_Title = title;
153 es.es_TextFormat = text;
154 es.es_GadgetFormat = gadtext;
156 return EasyRequestArgs(win, &es, NULL, NULL);
159 /****************************************************************************************/
161 VOID Cleanup(CONST_STRPTR msg)
163 WORD rc, i;
165 if (msg)
167 if (IntuitionBase && !((struct Process *)FindTask(NULL))->pr_CLI)
169 ShowMessage("More", msg, MSG(MSG_OK));
170 } else {
171 printf("More: %s\n", msg);
173 rc = RETURN_WARN;
174 } else {
175 rc = RETURN_OK;
178 CleanupRequesters();
180 KillMenus();
182 if (win)
184 for(i = 0; i < NUM_GADGETS;i++)
186 if (gad[i]) RemoveGadget(win, gad[i]);
189 CloseWindow(win);
192 for(i = 0; i < NUM_GADGETS;i++)
194 if (gad[i]) DisposeObject(gad[i]);
196 for(i = 0; i < NUM_IMAGES;i++)
198 if (img[i]) DisposeObject(img[i]);
201 if (vi) FreeVisualInfo(vi);
202 if (dri) FreeScreenDrawInfo(scr, dri);
203 if (scr) UnlockPubScreen(0, scr);
205 if (linearray) FreeVec(linearray);
206 if (filebuffer) FreeVec(filebuffer);
208 if (fh) Close(fh);
210 if (oldlock != (BPTR)-1) CurrentDir(oldlock);
212 if (GadToolsBase) CloseLibrary(GadToolsBase);
213 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
214 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
216 if (MyArgs) FreeArgs(MyArgs);
217 CleanupLocale();
219 exit(rc);
222 /****************************************************************************************/
224 static void DosError(void)
226 Fault(IoErr(), 0, s, 255);
227 if (in_main_loop)
229 ShowMessage("More", s, MSG(MSG_OK));
230 } else {
231 Cleanup(s);
235 /****************************************************************************************/
237 static void GetArguments(int argc, char **argv)
239 if (argc)
241 if (!(MyArgs = ReadArgs(ARG_TEMPLATE, Args, 0)))
243 DosError();
246 filename = (char *)Args[ARG_FILE];
248 else
250 struct WBStartup *startup = (struct WBStartup *) argv;
251 if (startup->sm_NumArgs > 1)
253 parentlock = startup->sm_ArgList[1].wa_Lock;
254 filename = startup->sm_ArgList[1].wa_Name;
255 if ((parentlock == NULL) || (filename == NULL))
256 Cleanup(NULL);
258 oldlock = CurrentDir(parentlock);
262 if (!filename) filename = GetFile(TRUE);
263 if (!filename) Cleanup(NULL);
265 strncpy(filenamebuffer, filename, 299);
269 /****************************************************************************************/
271 static void OpenLibs(void)
273 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))
275 sprintf(s, MSG(MSG_CANT_OPEN_LIB), "intuition.library", 39);
276 Cleanup(s);
279 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)))
281 sprintf(s, MSG(MSG_CANT_OPEN_LIB), "graphics.library", 39);
282 Cleanup(s);
285 if (!(GadToolsBase = OpenLibrary("gadtools.library", 39)))
287 sprintf(s, MSG(MSG_CANT_OPEN_LIB), "gadtools.library", 39);
288 Cleanup(s);
292 /****************************************************************************************/
294 static UWORD CalcTextLen(char *text)
296 char c;
297 UWORD rc = 0;
299 while((c = *text++))
301 if (c == '\t')
303 rc += tabsize;
304 } else {
305 rc++;
309 if (rc > MAX_TEXTLINELEN) rc = MAX_TEXTLINELEN;
311 return rc;
314 /****************************************************************************************/
316 static BOOL OpenFile(void)
318 struct LineNode *new_linearray;
319 UBYTE *new_filebuffer;
320 LONG new_filelen;
321 LONG new_num_lines;
323 struct LineNode *linepos;
324 UBYTE *filepos;
325 LONG flen, act_line;
327 BOOL seekable;
329 if (!(fh = Open(filename, MODE_OLDFILE)))
331 DosError();
332 return FALSE;
335 if (Seek(fh, 0, OFFSET_END) >= 0) {
336 new_filelen = Seek(fh, 0, OFFSET_BEGINNING);
337 seekable = TRUE;
339 else {
340 new_filelen = 0x10000;
341 seekable = FALSE;
344 if (new_filelen < 0)
346 Close(fh); fh = 0;
347 DosError();
348 return FALSE;
351 if (!(new_filebuffer = AllocVec(new_filelen + 1, MEMF_PUBLIC)))
353 Close(fh); fh = 0;
354 if (in_main_loop)
356 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
357 return FALSE;
359 Cleanup(MSG(MSG_NO_MEM));
362 if ((flen=Read(fh, new_filebuffer, new_filelen)) != new_filelen && seekable)
364 FreeVec(new_filebuffer);
365 Close(fh); fh = 0;
366 DosError();
367 return FALSE;
370 new_filelen = flen;
371 new_filebuffer[new_filelen] = '\0';
373 Close(fh);fh = 0;
375 filepos = new_filebuffer;
377 new_num_lines = 1;
379 while(flen--)
381 if (*filepos++ == '\n') new_num_lines++;
384 new_linearray = AllocVec(new_num_lines * sizeof(struct LineNode), MEMF_PUBLIC | MEMF_CLEAR);
385 if (!new_linearray)
387 FreeVec(new_filebuffer);
388 if (in_main_loop)
390 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
391 return FALSE;
393 Cleanup(MSG(MSG_NO_MEM));
396 linepos = new_linearray;
397 filepos = new_filebuffer;
399 act_line = 1;
400 max_textlen = 0;
401 while(act_line <= new_num_lines)
403 linepos->text = (char *)filepos;
405 while ((*filepos != '\n') && (*filepos != '\0'))
407 linepos->stringlen++; filepos++;
410 *filepos++ = '\0';
412 linepos->textlen = CalcTextLen(linepos->text);
413 if (linepos->textlen > max_textlen) max_textlen = linepos->textlen;
415 linepos++; act_line++;
418 if (filebuffer) FreeVec(filebuffer);
419 if (linearray) FreeVec(linearray);
421 filebuffer = new_filebuffer;
422 filelen = new_filelen;
423 linearray = new_linearray;
424 num_lines = new_num_lines;
426 return TRUE;
429 /****************************************************************************************/
431 static void GetVisual(void)
433 if (!(scr = LockPubScreen(0)))
435 Cleanup(MSG(MSG_CANT_LOCK_SCR));
438 if (!(dri = GetScreenDrawInfo(scr)))
440 Cleanup(MSG(MSG_CANT_GET_DRI));
443 if (!(vi = GetVisualInfoA(scr, 0)))
445 Cleanup(MSG(MSG_CANT_GET_VI));
448 shinepen = dri->dri_Pens[SHINEPEN];
449 shadowpen = dri->dri_Pens[SHADOWPEN];
450 textpen = dri->dri_Pens[TEXTPEN];
451 bgpen = dri->dri_Pens[BACKGROUNDPEN];
454 /****************************************************************************************/
456 static void MakeGadgets(void)
458 static WORD img2which[] =
460 UPIMAGE,
461 DOWNIMAGE,
462 LEFTIMAGE,
463 RIGHTIMAGE,
464 SIZEIMAGE
467 IPTR imagew[NUM_IMAGES], imageh[NUM_IMAGES];
468 WORD v_offset, h_offset, btop, i;
470 for(i = 0;i < NUM_IMAGES;i++)
472 img[i] = NewObject(0, SYSICLASS, SYSIA_DrawInfo , (Tag) dri,
473 SYSIA_Which , (Tag) img2which[i],
474 TAG_DONE);
476 if (!img[i]) Cleanup(MSG(MSG_CANT_CREATE_SYSIMAGE));
478 GetAttr(IA_Width, (Object *)img[i], &imagew[i]);
479 GetAttr(IA_Height, (Object *)img[i], &imageh[i]);
482 btop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;
484 v_offset = imagew[IMG_DOWNARROW] / 4;
485 h_offset = imageh[IMG_LEFTARROW] / 4;
487 firstgadget =
488 gad[GAD_UPARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_UPARROW] ,
489 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
490 GA_RelBottom , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
491 GA_ID , GAD_UPARROW ,
492 GA_RightBorder, TRUE ,
493 GA_Immediate , TRUE ,
494 GA_RelVerify , TRUE ,
495 TAG_DONE);
497 gad[GAD_DOWNARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_DOWNARROW] ,
498 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
499 GA_RelBottom , -imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
500 GA_ID , GAD_DOWNARROW ,
501 GA_RightBorder , TRUE ,
502 GA_Previous , (Tag)gad[GAD_UPARROW] ,
503 GA_Immediate , TRUE ,
504 GA_RelVerify , TRUE ,
505 TAG_DONE);
507 gad[GAD_VERTSCROLL] = NewObject(0, PROPGCLASS, GA_Top , btop + 1 ,
508 GA_RelRight , -imagew[IMG_DOWNARROW] + v_offset + 1 ,
509 GA_Width , imagew[IMG_DOWNARROW] - v_offset * 2 ,
510 GA_RelHeight , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] - btop -2 ,
511 GA_ID , GAD_VERTSCROLL ,
512 GA_Previous , (Tag)gad[GAD_DOWNARROW] ,
513 GA_RightBorder , TRUE ,
514 GA_RelVerify , TRUE ,
515 GA_Immediate , TRUE ,
516 PGA_NewLook , TRUE ,
517 PGA_Borderless , TRUE ,
518 PGA_Total , 100 ,
519 PGA_Visible , 100 ,
520 PGA_Freedom , FREEVERT ,
521 TAG_DONE);
523 gad[GAD_RIGHTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_RIGHTARROW] ,
524 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] + 1,
525 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
526 GA_ID , GAD_RIGHTARROW ,
527 GA_BottomBorder , TRUE ,
528 GA_Previous , (Tag)gad[GAD_VERTSCROLL] ,
529 GA_Immediate , TRUE ,
530 GA_RelVerify , TRUE ,
531 TAG_DONE);
533 gad[GAD_LEFTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_LEFTARROW] ,
534 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] - imagew[IMG_LEFTARROW] + 1,
535 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
536 GA_ID , GAD_LEFTARROW ,
537 GA_BottomBorder , TRUE ,
538 GA_Previous , (Tag)gad[GAD_RIGHTARROW] ,
539 GA_Immediate , TRUE ,
540 GA_RelVerify , TRUE ,
541 TAG_DONE);
543 gad[GAD_HORIZSCROLL] = NewObject(0, PROPGCLASS, GA_Left , scr->WBorLeft,
544 GA_RelBottom , -imageh[IMG_LEFTARROW] + h_offset + 1 ,
545 GA_RelWidth , -imagew[IMG_LEFTARROW] - imagew[IMG_RIGHTARROW] - imagew[IMG_SIZE] - scr->WBorRight - 2,
546 GA_Height , imageh[IMG_LEFTARROW] - (h_offset * 2) ,
547 GA_ID , GAD_HORIZSCROLL ,
548 GA_Previous , (Tag)gad[GAD_LEFTARROW] ,
549 GA_BottomBorder , TRUE ,
550 GA_RelVerify , TRUE ,
551 GA_Immediate , TRUE ,
552 PGA_NewLook , TRUE ,
553 PGA_Borderless , TRUE ,
554 PGA_Total , 100 ,
555 PGA_Visible , 100 ,
556 PGA_Freedom , FREEHORIZ ,
557 TAG_DONE);
559 for(i = 0;i < NUM_GADGETS;i++)
561 if (!gad[i]) Cleanup(MSG(MSG_CANT_CREATE_GADGET));
565 /****************************************************************************************/
567 static void CalcVisible(void)
569 visiblex = (win->Width - borderleft - borderright -
570 INNER_SPACING_X * 2) / fontwidth;
572 visibley = (win->Height - bordertop - borderbottom -
573 INNER_SPACING_Y * 2) / fontheight;
575 if (visiblex < 1) visiblex = 1;
576 if (visibley < 1) visibley = 1;
578 textendx = textstartx + visiblex * fontwidth - 1;
579 textendy = textstarty + visibley * fontheight - 1;
581 textwidth = textendx - textstartx + 1;
582 textheight = textendy - textstarty + 1;
585 /****************************************************************************************/
587 static void MySetAPen(struct RastPort *rp, LONG reg)
589 static LONG oldreg = -1;
591 if (reg != oldreg)
593 oldreg = reg;
594 SetAPen(rp, reg);
598 /****************************************************************************************/
600 static void MySetBPen(struct RastPort *rp, LONG reg)
602 static LONG oldreg = -1;
604 if (reg != oldreg)
606 oldreg = reg;
607 SetBPen(rp, reg);
611 /****************************************************************************************/
613 static void DrawTextLine(WORD viewline, WORD columns, BOOL clearright)
615 static char tempstring[MAX_TEXTLINELEN + 1];
616 static char c, *stringpos, *text;
617 LONG realline = viewline + viewstarty;
618 WORD textlen, i = 0, t, x;
619 BOOL inverted;
621 /* column < 0 means draw only first -column chars
623 ** column > 0 means draw only last column chars
625 ** column = 0 means draw whole line
628 if (columns != 0)
630 clearright = FALSE; /* because already cleared by ScrollRaster */
633 if ((viewline >= 0) && (viewline < visibley) &&
634 (realline >= 0) && (realline < num_lines))
636 inverted = linearray[realline].invert;
638 text = linearray[realline].text;
639 textlen = linearray[realline].textlen;
641 stringpos = tempstring;
643 while((c = *text++) && (i < textlen))
645 if (c == '\t')
647 for(t = 0; (t < tabsize) && (i < textlen);t++)
649 *stringpos++ = ' ';
650 i++;
652 } else {
653 *stringpos++ = c;
654 i++;
656 } /* while((c = *text++) && (i < textlen)) */
658 stringpos = tempstring + viewstartx;
659 i -= viewstartx;
661 if (i < 0)
663 i = 0;
664 } else {
665 if (i > visiblex) i = visiblex;
667 x = textstartx;
668 if (columns < 0)
670 if (i > (-columns)) i = (-columns);
671 } else if (columns > 0) {
672 x = textstartx + (visiblex - columns) * fontwidth;
673 stringpos += (visiblex - columns);
674 i -= (visiblex - columns);
677 if (i > 0)
679 MySetAPen(rp, textpen);
680 MySetBPen(rp, inverted ? shinepen : bgpen);
682 Move(rp, x,
683 textstarty + (viewline * fontheight) + fontbaseline);
685 Text(rp, stringpos, i);
689 } /* if ((realline >= 0) && (realline < num_lines)) */
691 if ((i < visiblex) && clearright)
693 MySetAPen(rp, bgpen);
694 RectFill(rp, textstartx + (i * fontwidth),
695 textstarty + (viewline * fontheight),
696 textendx,
697 textstarty + (viewline * fontheight) + fontheight - 1);
701 /****************************************************************************************/
703 static void DrawAllText(void)
705 WORD y;
707 for(y = 0;y < visibley;y++)
709 DrawTextLine(y, 0, TRUE);
713 /****************************************************************************************/
715 static void SetWinTitle(void)
717 static UBYTE wintitle[256];
718 BPTR lock;
720 strcpy(s, filename);
721 if ((lock = Lock(filename, SHARED_LOCK)))
723 NameFromLock(lock, s, 255);
724 UnLock(lock);
726 sprintf(wintitle, MSG(MSG_WIN_TITLE), s, num_lines, filelen);
728 SetWindowTitles(win, wintitle, (UBYTE *)~0L);
731 /****************************************************************************************/
733 static void MakeWin(void)
735 if (!(win = OpenWindowTags(NULL, WA_PubScreen , (IPTR)scr ,
736 WA_Left , 0 ,
737 WA_Top , scr->BarHeight + 1 ,
738 WA_Width , 600 ,
739 WA_Height , 300 ,
740 WA_AutoAdjust , TRUE ,
741 USE_SIMPLEREFRESH ?
742 WA_SimpleRefresh :
743 TAG_IGNORE , TRUE ,
744 WA_CloseGadget , TRUE ,
745 WA_DepthGadget , TRUE ,
746 WA_DragBar , TRUE ,
747 WA_SizeGadget , TRUE ,
748 WA_SizeBBottom , TRUE ,
749 WA_SizeBRight , TRUE ,
750 WA_Activate , TRUE ,
751 WA_Gadgets , (IPTR)firstgadget ,
752 WA_MinWidth , 100 ,
753 WA_MinHeight , 100 ,
754 WA_MaxWidth , scr->Width ,
755 WA_MaxHeight , scr->Height ,
756 WA_ReportMouse , TRUE ,
757 WA_NewLookMenus , TRUE ,
758 WA_IDCMP , IDCMP_CLOSEWINDOW |
759 IDCMP_NEWSIZE |
760 IDCMP_GADGETDOWN |
761 IDCMP_GADGETUP |
762 IDCMP_MOUSEMOVE |
763 IDCMP_VANILLAKEY |
764 IDCMP_INTUITICKS |
765 (USE_SIMPLEREFRESH != 0) * IDCMP_REFRESHWINDOW |
766 IDCMP_RAWKEY |
767 IDCMP_MENUPICK ,
768 TAG_DONE)))
770 Cleanup(MSG(MSG_CANT_CREATE_WIN));
773 SetWinTitle();
775 winmask = 1L << win->UserPort->mp_SigBit;
777 winwidth = win->Width;
778 winheight = win->Height;
780 rp = win->RPort;
782 SetDrMd(rp, JAM2);
784 #ifdef USE_WRITEMASK
785 SetWriteMask(rp, 0x3);
786 #endif
788 fontwidth = rp->TxWidth;
789 fontheight = rp->TxHeight;
790 fontbaseline = rp->TxBaseline;
792 borderleft = win->BorderLeft;
793 bordertop = win->BorderTop;
794 borderright = win->BorderRight;
795 borderbottom = win->BorderBottom;
797 textstartx = borderleft + INNER_SPACING_X;
798 textstarty = bordertop + INNER_SPACING_Y;
800 CalcVisible();
802 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , 0 ,
803 PGA_Total , max_textlen ,
804 PGA_Visible , visiblex ,
805 TAG_DONE);
807 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , 0 ,
808 PGA_Total , num_lines ,
809 PGA_Visible , visibley ,
810 TAG_DONE);
812 DrawAllText();
814 SetMenuStrip(win, menus);
817 /****************************************************************************************/
819 static void NewWinSize(void)
821 WORD new_winwidth, new_winheight;
823 new_winwidth = win->Width;
824 new_winheight = win->Height;
826 CalcVisible();
828 if ((viewstartx + visiblex) > max_textlen)
830 viewstartx = max_textlen - visiblex;
831 if (viewstartx < 0) viewstartx = 0;
834 if ((viewstarty + visibley) > num_lines)
836 viewstarty = num_lines - visibley;
837 if (viewstarty < 0) viewstarty = 0;
840 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
841 PGA_Visible , visiblex ,
842 TAG_DONE);
844 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
845 PGA_Visible , visibley ,
846 TAG_DONE);
848 if (new_winwidth < winwidth)
850 MySetAPen(rp, bgpen);
851 RectFill(rp, textendx + 1,
852 bordertop + INNER_SPACING_Y,
853 new_winwidth - borderright - 1,
854 new_winheight - borderbottom - 1);
857 if (new_winheight < winheight)
859 MySetAPen(rp, bgpen);
860 RectFill(rp, borderleft + INNER_SPACING_X,
861 textendy + 1,
862 new_winwidth - borderright - 1,
863 new_winheight - borderbottom - 1);
866 if ((new_winwidth > winwidth) ||
867 (new_winheight > winheight))
869 DrawAllText();
872 winwidth = new_winwidth;
873 winheight = new_winheight;
876 /****************************************************************************************/
878 #ifdef USE_SIMPLEREFRESH
880 /****************************************************************************************/
882 static void RefreshAll(void)
884 DrawAllText();
887 /****************************************************************************************/
889 static void HandleRefresh(void)
891 BeginRefresh(win);
892 RefreshAll();
893 EndRefresh(win, TRUE);
896 /****************************************************************************************/
898 #endif /* USE_SIMPLEREFRESH */
900 /****************************************************************************************/
902 static void ScrollTo(WORD gadid, LONG top, BOOL refreshprop)
904 LONG y, dx, dy;
906 MySetBPen(rp, bgpen);
908 switch(gadid)
910 case GAD_VERTSCROLL:
911 if (top + visibley > num_lines)
913 top = num_lines - visibley;
915 if (top < 0) top = 0;
917 if (top != viewstarty )
919 dy = top - viewstarty;
920 viewstarty = top;
922 if (refreshprop)
924 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstarty,
925 TAG_DONE);
928 if (abs(dy) >= visibley)
930 DrawAllText();
931 } else {
932 if (dy > 0)
935 #ifdef USE_SIMPLEREFRESH
936 ScrollRaster(rp,
938 fontheight * dy,
939 textstartx,
940 textstarty,
941 textendx,
942 textendy);
944 if (rp->Layer->Flags & LAYERREFRESH)
946 HandleRefresh();
948 #else
949 ClipBlit(rp, textstartx,
950 textstarty + dy * fontheight,
951 rp, textstartx,
952 textstarty,
953 textwidth,
954 textheight - dy * fontheight,
955 192);
956 #endif
958 for (y = visibley - dy;y < visibley;y++)
960 DrawTextLine(y, 0, TRUE);
962 } else {
963 dy = -dy;
965 #ifdef USE_SIMPLEREFRESH
966 ScrollRaster(rp,
968 -fontheight * dy,
969 textstartx,
970 textstarty,
971 textendx,
972 textendy);
974 if (rp->Layer->Flags & LAYERREFRESH)
976 HandleRefresh();
979 #else
980 ClipBlit(rp, textstartx,
981 textstarty,
982 rp, textstartx,
983 textstarty + dy * fontheight,
984 textwidth,
985 textheight - dy * fontheight,
986 192);
987 #endif
988 for (y = 0;y < dy;y++)
990 DrawTextLine(y, 0, TRUE);
995 } /* if (top != viewstarty ) */
996 break;
998 case GAD_HORIZSCROLL:
999 if (top + visiblex > max_textlen)
1001 top = max_textlen - visiblex;
1003 if (top < 0) top = 0;
1005 if (top != viewstartx )
1007 dx = top - viewstartx;
1008 viewstartx = top;
1010 if (refreshprop)
1012 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstartx,
1013 TAG_DONE);
1016 if (abs(dx) >= visiblex)
1018 DrawAllText();
1019 } else {
1020 if (dx > 0)
1023 #ifdef USE_SIMPLEREFRESH
1024 ScrollRaster(rp,
1025 fontwidth * dx,
1027 textstartx,
1028 textstarty,
1029 textendx,
1030 textendy);
1032 if (rp->Layer->Flags & LAYERREFRESH)
1034 HandleRefresh();
1036 #else
1037 ClipBlit(rp, textstartx + dx * fontwidth,
1038 textstarty,
1039 rp, textstartx,
1040 textstarty,
1041 textwidth - dx * fontwidth,
1042 textheight,
1043 192);
1044 #endif
1045 for (y = 0;y < visibley;y++)
1047 DrawTextLine(y, dx, TRUE);
1050 } else {
1051 dx = -dx;
1053 #ifdef USE_SIMPLEREFRESH
1054 ScrollRaster(rp,
1055 -fontwidth * dx,
1057 textstartx,
1058 textstarty,
1059 textendx,
1060 textendy);
1062 if (rp->Layer->Flags & LAYERREFRESH)
1064 HandleRefresh();
1067 #else
1068 ClipBlit(rp, textstartx,
1069 textstarty,
1070 rp, textstartx + dx * fontwidth,
1071 textstarty,
1072 textwidth - dx * fontwidth,
1073 textheight,
1074 192);
1075 #endif
1076 for (y = 0;y < visibley;y++)
1078 DrawTextLine(y, -dx, TRUE);
1083 } /* if (top != viewstartx ) */
1084 break;
1086 } /* switch(gadid) */
1090 /****************************************************************************************/
1092 static void HandleScrollGadget(WORD gadid)
1094 struct IntuiMessage *msg;
1095 IPTR top;
1096 BOOL ok=FALSE;
1098 while (!ok)
1100 WaitPort(win->UserPort);
1101 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1103 switch (msg->Class)
1105 case IDCMP_GADGETUP:
1106 ok=TRUE;
1107 /* fall through */
1109 case IDCMP_MOUSEMOVE:
1110 GetAttr(PGA_Top, (Object *)gad[gadid], &top);
1111 ScrollTo(gadid, top, FALSE);
1112 break;
1114 #ifdef USE_SIMPLEREFRESH
1115 case IDCMP_REFRESHWINDOW:
1116 HandleRefresh();
1117 break;
1118 #endif
1120 } /* switch (msg->Class) */
1121 ReplyMsg((struct Message *)msg);
1123 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1125 } /* while (!ok) */
1128 /****************************************************************************************/
1130 static BOOL FindString(struct LineNode *ln, char *search, LONG searchlen)
1132 char *text = ln->text;
1133 LONG textlen = ln->stringlen;
1134 LONG i;
1135 BOOL rc = FALSE;
1137 textlen -= searchlen;
1139 while(textlen >= 0)
1141 for(i = 0;i < searchlen;i++)
1143 if (toupper(text[i]) != toupper(search[i])) break;
1146 if (i == searchlen)
1148 rc = TRUE;
1149 break;
1151 text++;textlen--;
1154 return rc;
1157 /****************************************************************************************/
1159 static void DoSearch(WORD kind)
1161 LONG line, searchlen;
1162 BOOL done = FALSE;
1164 if (!searchtext) return;
1166 searchlen = strlen(searchtext);
1167 if (searchlen == 0) return;
1169 if (kind == SEARCH_NEW)
1171 search_startline = 0;
1172 kind = SEARCH_NEXT;
1175 line = search_startline;
1177 while(!done)
1179 if (FindString(&linearray[line], searchtext, searchlen))
1181 done = TRUE;
1182 if (found_line >= 0)
1184 linearray[found_line].invert = FALSE;
1185 DrawTextLine(found_line - viewstarty, 0, TRUE);
1188 ScrollTo(GAD_VERTSCROLL, line - visibley / 2, TRUE);
1190 found_line = line;
1191 linearray[found_line].invert = TRUE;
1192 DrawTextLine(found_line - viewstarty, 0, TRUE);
1195 if (kind == SEARCH_NEXT)
1197 line++;
1198 if (line < num_lines)
1200 search_startline = line;
1201 } else {
1202 done = TRUE;
1203 DisplayBeep(NULL);
1205 } else {
1206 line--;
1207 if (line >= 0)
1209 search_startline = line;
1210 } else {
1211 done = TRUE;
1212 DisplayBeep(NULL);
1216 } /* while(!done) */
1220 /****************************************************************************************/
1222 static BOOL HandleWin(void)
1224 struct IntuiMessage *msg;
1225 struct MenuItem *item;
1226 WORD gadid, delta;
1227 UWORD men, code;
1228 UBYTE key;
1229 BOOL pagescroll, maxscroll, quitme = FALSE;
1231 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1233 switch(msg->Class)
1235 case IDCMP_CLOSEWINDOW:
1236 quitme = TRUE;
1237 break;
1239 case IDCMP_NEWSIZE:
1240 NewWinSize();
1241 break;
1243 #ifdef USE_SIMPLEREFRESH
1244 case IDCMP_REFRESHWINDOW:
1245 HandleRefresh();
1246 break;
1247 #endif
1248 case IDCMP_GADGETDOWN:
1249 gadid = ((struct Gadget *)msg->IAddress)->GadgetID;
1250 arrowticker = 3;
1252 switch(gadid)
1254 case GAD_HORIZSCROLL:
1255 case GAD_VERTSCROLL:
1256 HandleScrollGadget(gadid);
1257 break;
1259 case GAD_UPARROW:
1260 activearrowgad = (struct Gadget *)msg->IAddress;
1261 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1262 break;
1264 case GAD_DOWNARROW:
1265 activearrowgad = (struct Gadget *)msg->IAddress;
1266 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1267 break;
1269 case GAD_LEFTARROW:
1270 activearrowgad = (struct Gadget *)msg->IAddress;
1271 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1272 break;
1274 case GAD_RIGHTARROW:
1275 activearrowgad = (struct Gadget *)msg->IAddress;
1276 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1277 break;
1279 break;
1281 case IDCMP_INTUITICKS:
1282 if (activearrowgad)
1284 if (arrowticker)
1286 arrowticker--;
1288 else if (activearrowgad->Flags & GFLG_SELECTED)
1290 switch(activearrowgad->GadgetID)
1292 case GAD_UPARROW:
1293 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1294 break;
1296 case GAD_DOWNARROW:
1297 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1298 break;
1300 case GAD_LEFTARROW:
1301 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1302 break;
1304 case GAD_RIGHTARROW:
1305 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1306 break;
1310 break;
1312 case IDCMP_GADGETUP:
1313 activearrowgad = NULL;
1314 break;
1316 case IDCMP_VANILLAKEY:
1317 key = toupper(msg->Code);
1318 if (key == 27)
1320 quitme = TRUE;
1322 else if (key == ' ')
1324 ScrollTo(GAD_VERTSCROLL, viewstarty + visibley - 1, TRUE);
1326 else if (key == 8)
1328 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1330 else if (key == 13)
1332 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1334 else if (strchr(MSG(MSG_SHORTCUT_TOP), key))
1336 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1338 else if (strchr(MSG(MSG_SHORTCUT_BOTTOM), key))
1340 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1342 else if (strchr(MSG(MSG_SHORTCUT_JUMP), key))
1344 Make_Goto_Requester();
1346 else if (strchr(MSG(MSG_SHORTCUT_FIND), key))
1348 Make_Find_Requester();
1350 else if (strchr(MSG(MSG_SHORTCUT_NEXT), key))
1352 DoSearch(SEARCH_NEXT);
1354 else if (strchr(MSG(MSG_SHORTCUT_NEXT), key))
1356 DoSearch(SEARCH_PREV);
1358 break;
1360 case IDCMP_RAWKEY:
1361 pagescroll = (0 != (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)));
1362 maxscroll = (0 != (msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT | IEQUALIFIER_CONTROL)));
1364 code = msg->Code; delta = 1;
1366 switch(code)
1368 case RAWKEY_NM_WHEEL_UP:
1369 code = CURSORUP;
1370 delta = 3;
1371 break;
1373 case RAWKEY_NM_WHEEL_DOWN:
1374 code = CURSORDOWN;
1375 delta = 3;
1376 break;
1378 case RAWKEY_NM_WHEEL_LEFT:
1379 code = CURSORLEFT;
1380 delta = 3;
1381 break;
1383 case RAWKEY_NM_WHEEL_RIGHT:
1384 code = CURSORRIGHT;
1385 delta = 3;
1386 break;
1389 switch(code)
1391 case CURSORUP:
1392 ScrollTo(GAD_VERTSCROLL,
1393 maxscroll ? 0 : viewstarty - (pagescroll ? visibley - 1 : delta),
1394 TRUE);
1395 break;
1397 case CURSORDOWN:
1398 ScrollTo(GAD_VERTSCROLL,
1399 maxscroll ? num_lines : viewstarty + (pagescroll ? visibley - 1 : delta),
1400 TRUE);
1401 break;
1403 case CURSORLEFT:
1404 ScrollTo(GAD_HORIZSCROLL,
1405 maxscroll ? 0 : viewstartx - (pagescroll ? visiblex - 1 : delta),
1406 TRUE);
1407 break;
1409 case CURSORRIGHT:
1410 ScrollTo(GAD_HORIZSCROLL,
1411 maxscroll ? max_textlen : viewstartx + (pagescroll ? visiblex - 1 : delta),
1412 TRUE);
1413 break;
1415 case RAWKEY_HOME:
1416 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1417 break;
1419 case RAWKEY_END:
1420 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1421 break;
1423 case RAWKEY_PAGEUP:
1424 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1425 break;
1427 case RAWKEY_PAGEDOWN:
1428 ScrollTo(GAD_VERTSCROLL, viewstarty + (visibley - 1), TRUE);
1429 break;
1431 } /* switch(msg->Code) */
1432 break;
1434 case IDCMP_MENUPICK:
1435 men = msg->Code;
1436 while(men != MENUNULL)
1438 if ((item = ItemAddress(menus, men)))
1440 switch((ULONG)GTMENUITEM_USERDATA(item))
1442 case MSG_MEN_PROJECT_SAVEAS:
1443 fillename_dest = GetFile(FALSE);
1444 if (!fillename_dest)
1445 break;
1447 case MSG_MEN_PROJECT_PRINT:
1448 sprintf(s, "Run >NIL: Type \"%s\" TO \"%s\"", filenamebuffer, fillename_dest ? fillename_dest : "PRT:");
1449 if (System(s, TAG_END))
1450 DisplayBeep(NULL);
1451 fillename_dest = NULL;
1452 break;
1454 case MSG_MEN_PROJECT_ABOUT:
1455 About();
1456 break;
1458 case MSG_MEN_PROJECT_QUIT:
1459 quitme = TRUE;
1460 break;
1462 case MSG_MEN_PROJECT_OPEN:
1463 if ((filename = GetFile(TRUE)))
1465 if (OpenFile())
1467 strncpy(filenamebuffer, filename, 299);
1468 SetWinTitle();
1469 MySetAPen(rp, bgpen);
1470 RectFill(rp, textstartx, textstarty, textendx, textendy);
1472 CalcVisible();
1474 viewstartx = viewstarty = 0;
1476 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
1477 PGA_Visible, visiblex ,
1478 PGA_Total , max_textlen ,
1479 TAG_DONE);
1481 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
1482 PGA_Visible , visibley ,
1483 PGA_Total , num_lines ,
1484 TAG_DONE);
1485 DrawAllText();
1487 } /* if (OpenFile()) */
1489 } /* if ((filename = GetFile())) */
1491 break;
1493 case MSG_MEN_NAVIGATION_FIND:
1494 Make_Find_Requester();
1495 break;
1497 case MSG_MEN_NAVIGATION_FIND_NEXT:
1498 DoSearch(SEARCH_NEXT);
1499 break;
1501 case MSG_MEN_NAVIGATION_FIND_PREV:
1502 DoSearch(SEARCH_PREV);
1503 break;
1505 case MSG_MEN_NAVIGATION_JUMP:
1506 Make_Goto_Requester();
1507 break;
1509 } /* switch(GTMENUITEM_USERDATA(item)) */
1511 men = item->NextSelect;
1512 } else {
1513 men = MENUNULL;
1516 } /* while(men != MENUNULL) */
1517 break;
1519 } /* switch(msg->Class) */
1521 ReplyMsg((struct Message *)msg);
1523 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1525 return quitme;
1528 /****************************************************************************************/
1530 static void HandleAll(void)
1532 ULONG sigs;
1533 LONG line;
1534 WORD search_kind;
1535 BOOL quitme = FALSE;
1537 in_main_loop = TRUE;
1539 ScreenToFront(win->WScreen);
1541 while(!quitme)
1543 sigs = Wait(winmask | gotomask | findmask);
1545 if (sigs & winmask) quitme = HandleWin();
1547 if (sigs & gotomask)
1549 if (Handle_Goto_Requester(&line))
1551 ScrollTo(GAD_VERTSCROLL, line - 1, TRUE);
1555 if (sigs & findmask)
1557 if ((search_kind = Handle_Find_Requester(&searchtext)))
1559 DoSearch(search_kind);
1563 } /* while(!quitme) */
1566 /****************************************************************************************/
1568 int main(int argc, char **argv)
1570 InitLocale("System/Utilities/More.catalog", 1);
1571 InitMenus();
1572 GetArguments(argc, argv);
1573 OpenLibs();
1574 OpenFile();
1575 GetVisual();
1576 MakeGadgets();
1577 MakeMenus();
1578 MakeWin();
1579 HandleAll();
1580 Cleanup(0);
1581 return 0;
1584 /****************************************************************************************/