grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / utilities / More / more.c
bloba75e4ec1ed1144702c046cb1e4175b246e6d4c47
1 /*
2 Copyright © 1995-2012, 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>
16 #include <workbench/workbench.h>
17 #include <proto/wb.h>
19 #include <graphics/gfx.h>
20 #include <utility/hooks.h>
21 #include <workbench/startup.h>
23 #include <proto/exec.h>
24 #include <proto/dos.h>
25 #include <proto/intuition.h>
26 #include <proto/graphics.h>
27 #include <proto/gadtools.h>
28 #include <proto/alib.h>
29 #include <proto/utility.h>
31 #include <setjmp.h>
32 #include <string.h>
33 #include <stdio.h>
35 #include "global.h"
36 #include "req.h"
38 #define CATCOMP_NUMBERS
39 #include "strings.h"
41 #define DEBUG 0
42 #include <aros/debug.h>
44 static inline int abs(int x)
46 if (x < 0)
47 return -x;
48 return x;
51 static jmp_buf exit_buf;
53 /****************************************************************************************/
55 /* #define USE_WRITEMASK */
56 #define USE_SIMPLEREFRESH 0
58 #define DEFAULT_TABSIZE 8
60 #define INNER_SPACING_X 2
61 #define INNER_SPACING_Y 2
63 #define MAX_TEXTLINELEN 4096
65 #define ARG_TEMPLATE "FILE"
67 enum
69 ARG_FILE,
70 NUM_ARGS
73 enum
75 GAD_UPARROW,
76 GAD_DOWNARROW,
77 GAD_LEFTARROW,
78 GAD_RIGHTARROW,
79 GAD_VERTSCROLL,
80 GAD_HORIZSCROLL,
81 NUM_GADGETS
84 enum
86 IMG_UPARROW,
87 IMG_DOWNARROW,
88 IMG_LEFTARROW,
89 IMG_RIGHTARROW,
90 IMG_SIZE,
91 NUM_IMAGES
94 /****************************************************************************************/
96 struct LineNode
98 char *text;
99 UWORD stringlen;
100 UWORD textlen;
101 BOOL invert;
104 /****************************************************************************************/
106 struct IntuitionBase *IntuitionBase;
107 struct GfxBase *GfxBase;
108 struct Library *GadToolsBase;
109 struct Screen *scr;
110 struct DrawInfo *dri;
111 APTR vi;
112 struct Menu *menus;
113 struct Window *win;
114 struct MsgPort *msgport;
115 struct AppWindow *appwindow;
117 ULONG gotomask, findmask;
118 UBYTE filenamebuffer[300];
120 /****************************************************************************************/
122 static struct RastPort *rp;
123 static struct RDArgs *MyArgs;
125 static struct Gadget *gad[NUM_GADGETS], *firstgadget, *activearrowgad;
126 static struct Image *img[NUM_GADGETS];
128 static struct LineNode *linearray;
130 static UBYTE *filebuffer;
132 static char *filename, *fillename_dest, s[256], *searchtext;
134 static BPTR fh;
136 static UWORD tabsize = DEFAULT_TABSIZE;
138 static WORD fontwidth, fontheight, borderleft, bordertop;
139 static WORD shinepen, shadowpen, bgpen, textpen;
140 static LONG borderright, borderbottom, visiblex, visibley;
141 static LONG fontbaseline, textstartx, textstarty, textendx, textendy;
142 static LONG textwidth, textheight, viewstartx, viewstarty;
143 static WORD winwidth, winheight;
145 static ULONG winmask, msgmask;
146 static LONG filelen, num_lines, max_textlen;
147 static LONG search_startline, found_line = -1;
148 static WORD arrowticker;
150 static BOOL in_main_loop;
152 static IPTR Args[NUM_ARGS];
154 static BPTR oldlock = (BPTR)-1;
155 static BPTR parentlock = (BPTR)-1;
157 /*********************************************************************************************/
159 WORD ShowMessage(CONST_STRPTR title, CONST_STRPTR text, CONST_STRPTR gadtext)
161 struct EasyStruct es;
163 es.es_StructSize = sizeof(es);
164 es.es_Flags = 0;
165 es.es_Title = title;
166 es.es_TextFormat = text;
167 es.es_GadgetFormat = gadtext;
169 return EasyRequestArgs(win, &es, NULL, NULL);
172 /****************************************************************************************/
174 VOID Cleanup(CONST_STRPTR msg)
176 WORD rc, i;
178 if (msg)
180 if (IntuitionBase && !((struct Process *)FindTask(NULL))->pr_CLI)
182 ShowMessage("More", msg, MSG(MSG_OK));
183 } else {
184 Printf("More: %s\n", msg);
186 rc = RETURN_WARN;
187 } else {
188 rc = RETURN_OK;
191 CleanupRequesters();
193 KillMenus();
195 if (appwindow)
197 RemoveAppWindow(appwindow);
199 if (msgport)
201 DeleteMsgPort(msgport);
204 if (win)
206 for(i = 0; i < NUM_GADGETS;i++)
208 if (gad[i]) RemoveGadget(win, gad[i]);
211 CloseWindow(win);
214 for(i = 0; i < NUM_GADGETS;i++)
216 if (gad[i]) DisposeObject(gad[i]);
218 for(i = 0; i < NUM_IMAGES;i++)
220 if (img[i]) DisposeObject(img[i]);
223 if (vi) FreeVisualInfo(vi);
224 if (dri) FreeScreenDrawInfo(scr, dri);
225 if (scr) UnlockPubScreen(0, scr);
227 if (linearray) FreeVec(linearray);
228 if (filebuffer) FreeVec(filebuffer);
230 if (fh) Close(fh);
232 if (oldlock != (BPTR)-1) CurrentDir(oldlock);
234 if (GadToolsBase) CloseLibrary(GadToolsBase);
235 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
236 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
238 if (MyArgs) FreeArgs(MyArgs);
239 CleanupLocale();
241 longjmp(exit_buf, rc);
244 /****************************************************************************************/
246 static void DosError(void)
248 Fault(IoErr(), 0, s, 255);
249 if (in_main_loop)
251 ShowMessage("More", s, MSG(MSG_OK));
252 } else {
253 Cleanup(s);
257 /****************************************************************************************/
259 static void GetArguments(int argc, char **argv)
261 if (argc)
263 if (!(MyArgs = ReadArgs(ARG_TEMPLATE, Args, 0)))
265 DosError();
268 filename = (char *)Args[ARG_FILE];
270 else
272 struct WBStartup *startup = (struct WBStartup *) argv;
273 if (startup->sm_NumArgs > 1)
275 parentlock = startup->sm_ArgList[1].wa_Lock;
276 filename = startup->sm_ArgList[1].wa_Name;
277 if ((parentlock == BNULL) || (filename == NULL))
278 Cleanup(NULL);
280 oldlock = CurrentDir(parentlock);
284 if (!filename) filename = GetFile(TRUE);
285 if (!filename) Cleanup(NULL);
287 strncpy(filenamebuffer, filename, 299);
291 /****************************************************************************************/
293 static void OpenLibs(void)
295 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))
297 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "intuition.library", 39);
298 Cleanup(s);
301 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)))
303 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "graphics.library", 39);
304 Cleanup(s);
307 if (!(GadToolsBase = OpenLibrary("gadtools.library", 39)))
309 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "gadtools.library", 39);
310 Cleanup(s);
314 /****************************************************************************************/
316 static UWORD CalcTextLen(char *text)
318 char c;
319 UWORD rc = 0;
321 while((c = *text++))
323 if (c == '\t')
325 rc += tabsize;
326 } else {
327 rc++;
331 if (rc > MAX_TEXTLINELEN) rc = MAX_TEXTLINELEN;
333 return rc;
336 /****************************************************************************************/
338 static BOOL OpenFile(void)
340 struct LineNode *new_linearray;
341 UBYTE *new_filebuffer;
342 LONG new_filelen;
343 LONG new_num_lines;
345 struct LineNode *linepos;
346 UBYTE *filepos;
347 LONG flen, act_line;
349 BOOL seekable;
351 if (!(fh = Open(filename, MODE_OLDFILE)))
353 DosError();
354 return FALSE;
357 if (Seek(fh, 0, OFFSET_END) >= 0) {
358 new_filelen = Seek(fh, 0, OFFSET_BEGINNING);
359 seekable = TRUE;
361 else {
362 new_filelen = 0x10000;
363 seekable = FALSE;
366 if (new_filelen < 0)
368 Close(fh); fh = 0;
369 DosError();
370 return FALSE;
373 if (!(new_filebuffer = AllocVec(new_filelen + 1, MEMF_PUBLIC)))
375 Close(fh); fh = 0;
376 if (in_main_loop)
378 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
379 return FALSE;
381 Cleanup(MSG(MSG_NO_MEM));
384 if ((flen=Read(fh, new_filebuffer, new_filelen)) != new_filelen && seekable)
386 FreeVec(new_filebuffer);
387 Close(fh); fh = 0;
388 DosError();
389 return FALSE;
392 new_filelen = flen;
393 new_filebuffer[new_filelen] = '\0';
395 Close(fh);fh = 0;
397 filepos = new_filebuffer;
399 new_num_lines = 1;
401 while(flen--)
403 if (*filepos++ == '\n') new_num_lines++;
406 new_linearray = AllocVec(new_num_lines * sizeof(struct LineNode), MEMF_PUBLIC | MEMF_CLEAR);
407 if (!new_linearray)
409 FreeVec(new_filebuffer);
410 if (in_main_loop)
412 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
413 return FALSE;
415 Cleanup(MSG(MSG_NO_MEM));
418 linepos = new_linearray;
419 filepos = new_filebuffer;
421 act_line = 1;
422 max_textlen = 0;
423 while(act_line <= new_num_lines)
425 linepos->text = (char *)filepos;
427 while ((*filepos != '\n') && (*filepos != '\0'))
429 linepos->stringlen++; filepos++;
432 *filepos++ = '\0';
434 linepos->textlen = CalcTextLen(linepos->text);
435 if (linepos->textlen > max_textlen) max_textlen = linepos->textlen;
437 linepos++; act_line++;
440 if (filebuffer) FreeVec(filebuffer);
441 if (linearray) FreeVec(linearray);
443 filebuffer = new_filebuffer;
444 filelen = new_filelen;
445 linearray = new_linearray;
446 num_lines = new_num_lines;
448 return TRUE;
451 /****************************************************************************************/
453 static void GetVisual(void)
455 if (!(scr = LockPubScreen(0)))
457 Cleanup(MSG(MSG_CANT_LOCK_SCR));
460 if (!(dri = GetScreenDrawInfo(scr)))
462 Cleanup(MSG(MSG_CANT_GET_DRI));
465 if (!(vi = GetVisualInfoA(scr, 0)))
467 Cleanup(MSG(MSG_CANT_GET_VI));
470 shinepen = dri->dri_Pens[SHINEPEN];
471 shadowpen = dri->dri_Pens[SHADOWPEN];
472 textpen = dri->dri_Pens[TEXTPEN];
473 bgpen = dri->dri_Pens[BACKGROUNDPEN];
476 /****************************************************************************************/
478 static void MakeGadgets(void)
480 static WORD img2which[] =
482 UPIMAGE,
483 DOWNIMAGE,
484 LEFTIMAGE,
485 RIGHTIMAGE,
486 SIZEIMAGE
489 IPTR imagew[NUM_IMAGES], imageh[NUM_IMAGES];
490 WORD v_offset, h_offset, btop, i;
492 for(i = 0;i < NUM_IMAGES;i++)
494 img[i] = NewObject(0, SYSICLASS, SYSIA_DrawInfo , (IPTR) dri,
495 SYSIA_Which , (IPTR) img2which[i],
496 TAG_DONE);
498 if (!img[i]) Cleanup(MSG(MSG_CANT_CREATE_SYSIMAGE));
500 GetAttr(IA_Width, (Object *)img[i], &imagew[i]);
501 GetAttr(IA_Height, (Object *)img[i], &imageh[i]);
504 btop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;
506 v_offset = imagew[IMG_DOWNARROW] / 4;
507 h_offset = imageh[IMG_LEFTARROW] / 4;
509 firstgadget =
510 gad[GAD_UPARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (IPTR)img[IMG_UPARROW] ,
511 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
512 GA_RelBottom , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
513 GA_ID , GAD_UPARROW ,
514 GA_RightBorder, TRUE ,
515 GA_Immediate , TRUE ,
516 GA_RelVerify , TRUE ,
517 TAG_DONE);
519 gad[GAD_DOWNARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (IPTR)img[IMG_DOWNARROW] ,
520 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
521 GA_RelBottom , -imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
522 GA_ID , GAD_DOWNARROW ,
523 GA_RightBorder , TRUE ,
524 GA_Previous , (IPTR)gad[GAD_UPARROW] ,
525 GA_Immediate , TRUE ,
526 GA_RelVerify , TRUE ,
527 TAG_DONE);
529 gad[GAD_VERTSCROLL] = NewObject(0, PROPGCLASS, GA_Top , btop + 1 ,
530 GA_RelRight , -imagew[IMG_DOWNARROW] + v_offset + 1 ,
531 GA_Width , imagew[IMG_DOWNARROW] - v_offset * 2 ,
532 GA_RelHeight , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] - btop -2 ,
533 GA_ID , GAD_VERTSCROLL ,
534 GA_Previous , (IPTR)gad[GAD_DOWNARROW] ,
535 GA_RightBorder , TRUE ,
536 GA_RelVerify , TRUE ,
537 GA_Immediate , TRUE ,
538 PGA_NewLook , TRUE ,
539 PGA_Borderless , TRUE ,
540 PGA_Total , 100 ,
541 PGA_Visible , 100 ,
542 PGA_Freedom , FREEVERT ,
543 TAG_DONE);
545 gad[GAD_RIGHTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (IPTR)img[IMG_RIGHTARROW] ,
546 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] + 1,
547 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
548 GA_ID , GAD_RIGHTARROW ,
549 GA_BottomBorder , TRUE ,
550 GA_Previous , (IPTR)gad[GAD_VERTSCROLL] ,
551 GA_Immediate , TRUE ,
552 GA_RelVerify , TRUE ,
553 TAG_DONE);
555 gad[GAD_LEFTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (IPTR)img[IMG_LEFTARROW] ,
556 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] - imagew[IMG_LEFTARROW] + 1,
557 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
558 GA_ID , GAD_LEFTARROW ,
559 GA_BottomBorder , TRUE ,
560 GA_Previous , (IPTR)gad[GAD_RIGHTARROW] ,
561 GA_Immediate , TRUE ,
562 GA_RelVerify , TRUE ,
563 TAG_DONE);
565 gad[GAD_HORIZSCROLL] = NewObject(0, PROPGCLASS, GA_Left , scr->WBorLeft,
566 GA_RelBottom , -imageh[IMG_LEFTARROW] + h_offset + 1 ,
567 GA_RelWidth , -imagew[IMG_LEFTARROW] - imagew[IMG_RIGHTARROW] - imagew[IMG_SIZE] - scr->WBorRight - 2,
568 GA_Height , imageh[IMG_LEFTARROW] - (h_offset * 2) ,
569 GA_ID , GAD_HORIZSCROLL ,
570 GA_Previous , (IPTR)gad[GAD_LEFTARROW] ,
571 GA_BottomBorder , TRUE ,
572 GA_RelVerify , TRUE ,
573 GA_Immediate , TRUE ,
574 PGA_NewLook , TRUE ,
575 PGA_Borderless , TRUE ,
576 PGA_Total , 100 ,
577 PGA_Visible , 100 ,
578 PGA_Freedom , FREEHORIZ ,
579 TAG_DONE);
581 for(i = 0;i < NUM_GADGETS;i++)
583 if (!gad[i]) Cleanup(MSG(MSG_CANT_CREATE_GADGET));
587 /****************************************************************************************/
589 static void CalcVisible(void)
591 visiblex = (win->Width - borderleft - borderright -
592 INNER_SPACING_X * 2) / fontwidth;
594 visibley = (win->Height - bordertop - borderbottom -
595 INNER_SPACING_Y * 2) / fontheight;
597 if (visiblex < 1) visiblex = 1;
598 if (visibley < 1) visibley = 1;
600 textendx = textstartx + visiblex * fontwidth - 1;
601 textendy = textstarty + visibley * fontheight - 1;
603 textwidth = textendx - textstartx + 1;
604 textheight = textendy - textstarty + 1;
607 /****************************************************************************************/
609 static void MySetAPen(struct RastPort *rp, LONG reg)
611 static LONG oldreg = -1;
613 if (reg != oldreg)
615 oldreg = reg;
616 SetAPen(rp, reg);
620 /****************************************************************************************/
622 static void MySetBPen(struct RastPort *rp, LONG reg)
624 static LONG oldreg = -1;
626 if (reg != oldreg)
628 oldreg = reg;
629 SetBPen(rp, reg);
633 /****************************************************************************************/
635 static void DrawTextLine(WORD viewline, WORD columns, BOOL clearright)
637 static char tempstring[MAX_TEXTLINELEN + 1];
638 static char c, *stringpos, *text;
639 LONG realline = viewline + viewstarty;
640 WORD textlen, i = 0, t, x;
641 BOOL inverted;
643 /* column < 0 means draw only first -column chars
645 ** column > 0 means draw only last column chars
647 ** column = 0 means draw whole line
650 if (columns != 0)
652 clearright = FALSE; /* because already cleared by ScrollRaster */
655 if ((viewline >= 0) && (viewline < visibley) &&
656 (realline >= 0) && (realline < num_lines))
658 inverted = linearray[realline].invert;
660 text = linearray[realline].text;
661 textlen = linearray[realline].textlen;
663 stringpos = tempstring;
665 while((c = *text++) && (i < textlen))
667 if (c == '\t')
669 for(t = 0; (t < tabsize) && (i < textlen);t++)
671 *stringpos++ = ' ';
672 i++;
674 } else {
675 *stringpos++ = c;
676 i++;
678 } /* while((c = *text++) && (i < textlen)) */
680 stringpos = tempstring + viewstartx;
681 i -= viewstartx;
683 if (i < 0)
685 i = 0;
686 } else {
687 if (i > visiblex) i = visiblex;
689 x = textstartx;
690 if (columns < 0)
692 if (i > (-columns)) i = (-columns);
693 } else if (columns > 0) {
694 x = textstartx + (visiblex - columns) * fontwidth;
695 stringpos += (visiblex - columns);
696 i -= (visiblex - columns);
699 if (i > 0)
701 MySetAPen(rp, textpen);
702 MySetBPen(rp, inverted ? shinepen : bgpen);
704 Move(rp, x,
705 textstarty + (viewline * fontheight) + fontbaseline);
707 Text(rp, stringpos, i);
711 } /* if ((realline >= 0) && (realline < num_lines)) */
713 if ((i < visiblex) && clearright)
715 MySetAPen(rp, bgpen);
716 RectFill(rp, textstartx + (i * fontwidth),
717 textstarty + (viewline * fontheight),
718 textendx,
719 textstarty + (viewline * fontheight) + fontheight - 1);
723 /****************************************************************************************/
725 static void DrawAllText(void)
727 WORD y;
729 for(y = 0;y < visibley;y++)
731 DrawTextLine(y, 0, TRUE);
735 /****************************************************************************************/
737 static void SetWinTitle(void)
739 static UBYTE wintitle[256];
740 BPTR lock;
742 strcpy(s, filename);
743 if ((lock = Lock(filename, SHARED_LOCK)))
745 NameFromLock(lock, s, 255);
746 UnLock(lock);
748 __sprintf(wintitle, MSG(MSG_WIN_TITLE), s, num_lines, filelen);
750 SetWindowTitles(win, wintitle, (UBYTE *)~0L);
753 /****************************************************************************************/
755 static void HandleFileChange(void)
757 strncpy(filenamebuffer, filename, 299);
758 SetWinTitle();
759 MySetAPen(rp, bgpen);
760 RectFill(rp, textstartx, textstarty, textendx, textendy);
762 CalcVisible();
764 viewstartx = viewstarty = 0;
766 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
767 PGA_Visible, visiblex ,
768 PGA_Total , max_textlen ,
769 TAG_DONE);
771 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
772 PGA_Visible , visibley ,
773 PGA_Total , num_lines ,
774 TAG_DONE);
775 DrawAllText();
779 /****************************************************************************************/
781 static void MakeWin(void)
783 if (!(win = OpenWindowTags(NULL, WA_PubScreen , (IPTR)scr ,
784 WA_Left , 0 ,
785 WA_Top , scr->BarHeight + 1 ,
786 WA_Width , 640 ,
787 WA_Height , 480 ,
788 WA_AutoAdjust , TRUE ,
789 USE_SIMPLEREFRESH ?
790 WA_SimpleRefresh :
791 TAG_IGNORE , TRUE ,
792 WA_CloseGadget , TRUE ,
793 WA_DepthGadget , TRUE ,
794 WA_DragBar , TRUE ,
795 WA_SizeGadget , TRUE ,
796 WA_SizeBBottom , TRUE ,
797 WA_SizeBRight , TRUE ,
798 WA_Activate , TRUE ,
799 WA_Gadgets , (IPTR)firstgadget ,
800 WA_MinWidth , 100 ,
801 WA_MinHeight , 100 ,
802 WA_MaxWidth , scr->Width ,
803 WA_MaxHeight , scr->Height ,
804 WA_ReportMouse , TRUE ,
805 WA_NewLookMenus , TRUE ,
806 WA_IDCMP , IDCMP_CLOSEWINDOW |
807 IDCMP_NEWSIZE |
808 IDCMP_GADGETDOWN |
809 IDCMP_GADGETUP |
810 IDCMP_MOUSEMOVE |
811 IDCMP_VANILLAKEY |
812 IDCMP_INTUITICKS |
813 (USE_SIMPLEREFRESH != 0) * IDCMP_REFRESHWINDOW |
814 IDCMP_RAWKEY |
815 IDCMP_MENUPICK ,
816 TAG_DONE)))
818 Cleanup(MSG(MSG_CANT_CREATE_WIN));
821 SetWinTitle();
823 winmask = 1L << win->UserPort->mp_SigBit;
825 if (!(msgport = CreateMsgPort()))
827 Cleanup(MSG(MSG_CANT_CREATE_MSGPORT));
829 if (!(appwindow = AddAppWindow(0,0,win,msgport,NULL)))
831 Cleanup(MSG(MSG_CANT_ADD_APPWINDOW));
833 msgmask = 1L << msgport->mp_SigBit;
835 winwidth = win->Width;
836 winheight = win->Height;
838 rp = win->RPort;
840 SetDrMd(rp, JAM2);
842 #ifdef USE_WRITEMASK
843 SetWriteMask(rp, 0x3);
844 #endif
846 fontwidth = rp->TxWidth;
847 fontheight = rp->TxHeight;
848 fontbaseline = rp->TxBaseline;
850 borderleft = win->BorderLeft;
851 bordertop = win->BorderTop;
852 borderright = win->BorderRight;
853 borderbottom = win->BorderBottom;
855 textstartx = borderleft + INNER_SPACING_X;
856 textstarty = bordertop + INNER_SPACING_Y;
858 CalcVisible();
860 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , 0 ,
861 PGA_Total , max_textlen ,
862 PGA_Visible , visiblex ,
863 TAG_DONE);
865 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , 0 ,
866 PGA_Total , num_lines ,
867 PGA_Visible , visibley ,
868 TAG_DONE);
870 DrawAllText();
872 SetMenuStrip(win, menus);
875 /****************************************************************************************/
877 static void NewWinSize(void)
879 WORD new_winwidth, new_winheight;
881 new_winwidth = win->Width;
882 new_winheight = win->Height;
884 CalcVisible();
886 if ((viewstartx + visiblex) > max_textlen)
888 viewstartx = max_textlen - visiblex;
889 if (viewstartx < 0) viewstartx = 0;
892 if ((viewstarty + visibley) > num_lines)
894 viewstarty = num_lines - visibley;
895 if (viewstarty < 0) viewstarty = 0;
898 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
899 PGA_Visible , visiblex ,
900 TAG_DONE);
902 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
903 PGA_Visible , visibley ,
904 TAG_DONE);
906 if (new_winwidth < winwidth)
908 MySetAPen(rp, bgpen);
909 RectFill(rp, textendx + 1,
910 bordertop + INNER_SPACING_Y,
911 new_winwidth - borderright - 1,
912 new_winheight - borderbottom - 1);
915 if (new_winheight < winheight)
917 MySetAPen(rp, bgpen);
918 RectFill(rp, borderleft + INNER_SPACING_X,
919 textendy + 1,
920 new_winwidth - borderright - 1,
921 new_winheight - borderbottom - 1);
924 if ((new_winwidth > winwidth) ||
925 (new_winheight > winheight))
927 DrawAllText();
930 winwidth = new_winwidth;
931 winheight = new_winheight;
934 /****************************************************************************************/
936 #ifdef USE_SIMPLEREFRESH
938 /****************************************************************************************/
940 static void RefreshAll(void)
942 DrawAllText();
945 /****************************************************************************************/
947 static void HandleRefresh(void)
949 BeginRefresh(win);
950 RefreshAll();
951 EndRefresh(win, TRUE);
954 /****************************************************************************************/
956 #endif /* USE_SIMPLEREFRESH */
958 /****************************************************************************************/
960 static void ScrollTo(WORD gadid, LONG top, BOOL refreshprop)
962 LONG y, dx, dy;
964 MySetBPen(rp, bgpen);
966 switch(gadid)
968 case GAD_VERTSCROLL:
969 if (top + visibley > num_lines)
971 top = num_lines - visibley;
973 if (top < 0) top = 0;
975 if (top != viewstarty )
977 dy = top - viewstarty;
978 viewstarty = top;
980 if (refreshprop)
982 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstarty,
983 TAG_DONE);
986 if (abs(dy) >= visibley)
988 DrawAllText();
989 } else {
990 if (dy > 0)
993 #ifdef USE_SIMPLEREFRESH
994 ScrollRaster(rp,
996 fontheight * dy,
997 textstartx,
998 textstarty,
999 textendx,
1000 textendy);
1002 if (rp->Layer->Flags & LAYERREFRESH)
1004 HandleRefresh();
1006 #else
1007 ClipBlit(rp, textstartx,
1008 textstarty + dy * fontheight,
1009 rp, textstartx,
1010 textstarty,
1011 textwidth,
1012 textheight - dy * fontheight,
1013 192);
1014 #endif
1016 for (y = visibley - dy;y < visibley;y++)
1018 DrawTextLine(y, 0, TRUE);
1020 } else {
1021 dy = -dy;
1023 #ifdef USE_SIMPLEREFRESH
1024 ScrollRaster(rp,
1026 -fontheight * dy,
1027 textstartx,
1028 textstarty,
1029 textendx,
1030 textendy);
1032 if (rp->Layer->Flags & LAYERREFRESH)
1034 HandleRefresh();
1037 #else
1038 ClipBlit(rp, textstartx,
1039 textstarty,
1040 rp, textstartx,
1041 textstarty + dy * fontheight,
1042 textwidth,
1043 textheight - dy * fontheight,
1044 192);
1045 #endif
1046 for (y = 0;y < dy;y++)
1048 DrawTextLine(y, 0, TRUE);
1053 } /* if (top != viewstarty ) */
1054 break;
1056 case GAD_HORIZSCROLL:
1057 if (top + visiblex > max_textlen)
1059 top = max_textlen - visiblex;
1061 if (top < 0) top = 0;
1063 if (top != viewstartx )
1065 dx = top - viewstartx;
1066 viewstartx = top;
1068 if (refreshprop)
1070 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstartx,
1071 TAG_DONE);
1074 if (abs(dx) >= visiblex)
1076 DrawAllText();
1077 } else {
1078 if (dx > 0)
1081 #ifdef USE_SIMPLEREFRESH
1082 ScrollRaster(rp,
1083 fontwidth * dx,
1085 textstartx,
1086 textstarty,
1087 textendx,
1088 textendy);
1090 if (rp->Layer->Flags & LAYERREFRESH)
1092 HandleRefresh();
1094 #else
1095 ClipBlit(rp, textstartx + dx * fontwidth,
1096 textstarty,
1097 rp, textstartx,
1098 textstarty,
1099 textwidth - dx * fontwidth,
1100 textheight,
1101 192);
1102 #endif
1103 for (y = 0;y < visibley;y++)
1105 DrawTextLine(y, dx, TRUE);
1108 } else {
1109 dx = -dx;
1111 #ifdef USE_SIMPLEREFRESH
1112 ScrollRaster(rp,
1113 -fontwidth * dx,
1115 textstartx,
1116 textstarty,
1117 textendx,
1118 textendy);
1120 if (rp->Layer->Flags & LAYERREFRESH)
1122 HandleRefresh();
1125 #else
1126 ClipBlit(rp, textstartx,
1127 textstarty,
1128 rp, textstartx + dx * fontwidth,
1129 textstarty,
1130 textwidth - dx * fontwidth,
1131 textheight,
1132 192);
1133 #endif
1134 for (y = 0;y < visibley;y++)
1136 DrawTextLine(y, -dx, TRUE);
1141 } /* if (top != viewstartx ) */
1142 break;
1144 } /* switch(gadid) */
1148 /****************************************************************************************/
1150 static void HandleScrollGadget(WORD gadid)
1152 struct IntuiMessage *msg;
1153 IPTR top;
1154 BOOL ok=FALSE;
1156 while (!ok)
1158 WaitPort(win->UserPort);
1159 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1161 switch (msg->Class)
1163 case IDCMP_GADGETUP:
1164 ok=TRUE;
1165 /* fall through */
1167 case IDCMP_MOUSEMOVE:
1168 GetAttr(PGA_Top, (Object *)gad[gadid], &top);
1169 ScrollTo(gadid, top, FALSE);
1170 break;
1172 #ifdef USE_SIMPLEREFRESH
1173 case IDCMP_REFRESHWINDOW:
1174 HandleRefresh();
1175 break;
1176 #endif
1178 } /* switch (msg->Class) */
1179 ReplyMsg((struct Message *)msg);
1181 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1183 } /* while (!ok) */
1186 /****************************************************************************************/
1188 static BOOL FindString(struct LineNode *ln, char *search, LONG searchlen)
1190 char *text = ln->text;
1191 LONG textlen = ln->stringlen;
1192 LONG i;
1193 BOOL rc = FALSE;
1195 textlen -= searchlen;
1197 while(textlen >= 0)
1199 for(i = 0;i < searchlen;i++)
1201 if (ToUpper(text[i]) != ToUpper(search[i])) break;
1204 if (i == searchlen)
1206 rc = TRUE;
1207 break;
1209 text++;textlen--;
1212 return rc;
1215 /****************************************************************************************/
1217 static void DoSearch(WORD kind)
1219 LONG line, searchlen;
1220 BOOL done = FALSE;
1222 if (!searchtext) return;
1224 searchlen = strlen(searchtext);
1225 if (searchlen == 0) return;
1227 line = search_startline;
1229 if (kind == SEARCH_NEXT && line < num_lines - 1)
1230 line++;
1231 else if (kind == SEARCH_PREV && line > 0)
1232 line--;
1234 if (kind == SEARCH_NEW)
1236 line = 0;
1237 kind = SEARCH_NEXT;
1240 while(!done)
1242 if (FindString(&linearray[line], searchtext, searchlen))
1244 done = TRUE;
1245 if (found_line >= 0)
1247 linearray[found_line].invert = FALSE;
1248 DrawTextLine(found_line - viewstarty, 0, TRUE);
1251 ScrollTo(GAD_VERTSCROLL, line - visibley / 2, TRUE);
1253 found_line = line;
1254 search_startline = line;
1255 linearray[found_line].invert = TRUE;
1256 DrawTextLine(found_line - viewstarty, 0, TRUE);
1259 if (kind == SEARCH_NEXT)
1261 line++;
1262 if (line >= num_lines)
1264 done = TRUE;
1265 DisplayBeep(NULL);
1267 } else {
1268 line--;
1269 if (line < 0)
1271 done = TRUE;
1272 DisplayBeep(NULL);
1276 } /* while(!done) */
1280 /****************************************************************************************/
1282 static BOOL HandleWin(void)
1284 struct IntuiMessage *msg;
1285 struct MenuItem *item;
1286 WORD gadid, delta;
1287 UWORD men, code;
1288 UBYTE key;
1289 BOOL pagescroll, maxscroll, quitme = FALSE;
1290 TEXT editorvarbuffer[300];
1291 struct AppMessage *appmsg;
1292 //struct WBArg *argptr;
1294 while ((appmsg = (struct AppMessage *) GetMsg(msgport)))
1296 if (appmsg->am_Type == AMTYPE_APPWINDOW)
1298 if (appmsg->am_NumArgs >= 1)
1300 NameFromLock(appmsg->am_ArgList->wa_Lock, filenamebuffer, 299);
1301 AddPart(filenamebuffer, appmsg->am_ArgList->wa_Name, 299);
1302 filename = filenamebuffer;
1303 D(bug("[More] appwindow received message: filename = %s\n", filename));
1307 ReplyMsg ((struct Message *) appmsg);
1308 ActivateWindow(win);
1310 if (OpenFile())
1311 HandleFileChange();
1313 } /* while ((appmsg = (struct AppMessage *) GetMsg(msgport))) */
1315 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1317 switch(msg->Class)
1319 case IDCMP_CLOSEWINDOW:
1320 quitme = TRUE;
1321 break;
1323 case IDCMP_NEWSIZE:
1324 NewWinSize();
1325 break;
1327 #ifdef USE_SIMPLEREFRESH
1328 case IDCMP_REFRESHWINDOW:
1329 HandleRefresh();
1330 break;
1331 #endif
1332 case IDCMP_GADGETDOWN:
1333 gadid = ((struct Gadget *)msg->IAddress)->GadgetID;
1334 arrowticker = 3;
1336 switch(gadid)
1338 case GAD_HORIZSCROLL:
1339 case GAD_VERTSCROLL:
1340 HandleScrollGadget(gadid);
1341 break;
1343 case GAD_UPARROW:
1344 activearrowgad = (struct Gadget *)msg->IAddress;
1345 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1346 break;
1348 case GAD_DOWNARROW:
1349 activearrowgad = (struct Gadget *)msg->IAddress;
1350 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1351 break;
1353 case GAD_LEFTARROW:
1354 activearrowgad = (struct Gadget *)msg->IAddress;
1355 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1356 break;
1358 case GAD_RIGHTARROW:
1359 activearrowgad = (struct Gadget *)msg->IAddress;
1360 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1361 break;
1363 break;
1365 case IDCMP_INTUITICKS:
1366 if (activearrowgad)
1368 if (arrowticker)
1370 arrowticker--;
1372 else if (activearrowgad->Flags & GFLG_SELECTED)
1374 switch(activearrowgad->GadgetID)
1376 case GAD_UPARROW:
1377 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1378 break;
1380 case GAD_DOWNARROW:
1381 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1382 break;
1384 case GAD_LEFTARROW:
1385 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1386 break;
1388 case GAD_RIGHTARROW:
1389 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1390 break;
1394 break;
1396 case IDCMP_GADGETUP:
1397 activearrowgad = NULL;
1398 break;
1400 case IDCMP_VANILLAKEY:
1401 key = ToUpper(msg->Code);
1402 if (key == 27)
1404 quitme = TRUE;
1406 else if (key == 8 || (key == ' ' && (0 != (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))))
1408 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1410 else if (key == ' ')
1412 ScrollTo(GAD_VERTSCROLL, viewstarty + visibley - 1, TRUE);
1414 else if (key == 13)
1416 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1418 else if (strchr(MSG(MSG_SHORTCUT_TOP), key))
1420 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1422 else if (strchr(MSG(MSG_SHORTCUT_BOTTOM), key))
1424 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1426 else if (strchr(MSG(MSG_SHORTCUT_JUMP), key))
1428 Make_Goto_Requester();
1430 else if (strchr(MSG(MSG_SHORTCUT_FIND), key))
1432 Make_Find_Requester();
1434 else if (strchr(MSG(MSG_SHORTCUT_NEXT), key))
1436 DoSearch(SEARCH_NEXT);
1438 else if (strchr(MSG(MSG_SHORTCUT_PREV), key))
1440 DoSearch(SEARCH_PREV);
1442 else if (strchr(MSG(MSG_SHORTCUT_EDITOR), key))
1444 if ( (GetVar("editor", editorvarbuffer, 299, GVF_GLOBAL_ONLY)) != -1L )
1446 __sprintf(s, "Run QUIET \"%s\" \"%s\"", editorvarbuffer, filenamebuffer );
1447 if (SystemTags(s, TAG_END))
1448 DisplayBeep(NULL);
1451 break;
1453 case IDCMP_RAWKEY:
1454 pagescroll = (0 != (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)));
1455 maxscroll = (0 != (msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT | IEQUALIFIER_CONTROL)));
1457 code = msg->Code; delta = 1;
1459 switch(code)
1461 case RAWKEY_NM_WHEEL_UP:
1462 code = CURSORUP;
1463 delta = 3;
1464 break;
1466 case RAWKEY_NM_WHEEL_DOWN:
1467 code = CURSORDOWN;
1468 delta = 3;
1469 break;
1471 case RAWKEY_NM_WHEEL_LEFT:
1472 code = CURSORLEFT;
1473 delta = 3;
1474 break;
1476 case RAWKEY_NM_WHEEL_RIGHT:
1477 code = CURSORRIGHT;
1478 delta = 3;
1479 break;
1482 switch(code)
1484 case CURSORUP:
1485 ScrollTo(GAD_VERTSCROLL,
1486 maxscroll ? 0 : viewstarty - (pagescroll ? visibley - 1 : delta),
1487 TRUE);
1488 break;
1490 case CURSORDOWN:
1491 ScrollTo(GAD_VERTSCROLL,
1492 maxscroll ? num_lines : viewstarty + (pagescroll ? visibley - 1 : delta),
1493 TRUE);
1494 break;
1496 case CURSORLEFT:
1497 ScrollTo(GAD_HORIZSCROLL,
1498 maxscroll ? 0 : viewstartx - (pagescroll ? visiblex - 1 : delta),
1499 TRUE);
1500 break;
1502 case CURSORRIGHT:
1503 ScrollTo(GAD_HORIZSCROLL,
1504 maxscroll ? max_textlen : viewstartx + (pagescroll ? visiblex - 1 : delta),
1505 TRUE);
1506 break;
1508 case RAWKEY_HOME:
1509 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1510 break;
1512 case RAWKEY_END:
1513 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1514 break;
1516 case RAWKEY_PAGEUP:
1517 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1518 break;
1520 case RAWKEY_PAGEDOWN:
1521 ScrollTo(GAD_VERTSCROLL, viewstarty + (visibley - 1), TRUE);
1522 break;
1524 } /* switch(msg->Code) */
1525 break;
1527 case IDCMP_MENUPICK:
1528 men = msg->Code;
1529 while(men != MENUNULL)
1531 if ((item = ItemAddress(menus, men)))
1533 switch((IPTR)GTMENUITEM_USERDATA(item))
1535 case MSG_MEN_PROJECT_SAVEAS:
1536 fillename_dest = GetFile(FALSE);
1537 if (!fillename_dest)
1538 break;
1540 case MSG_MEN_PROJECT_PRINT:
1541 __sprintf(s, "Run >NIL: Type \"%s\" TO \"%s\"", filenamebuffer, fillename_dest ? fillename_dest : "PRT:");
1542 if (System(s, TAG_END))
1543 DisplayBeep(NULL);
1544 fillename_dest = NULL;
1545 break;
1547 case MSG_MEN_PROJECT_ABOUT:
1548 About();
1549 break;
1551 case MSG_MEN_PROJECT_QUIT:
1552 quitme = TRUE;
1553 break;
1555 case MSG_MEN_PROJECT_OPEN:
1556 if ((filename = GetFile(TRUE)))
1558 if (OpenFile())
1560 HandleFileChange();
1561 } /* if (OpenFile()) */
1563 } /* if ((filename = GetFile())) */
1565 break;
1567 case MSG_MEN_NAVIGATION_FIND:
1568 Make_Find_Requester();
1569 break;
1571 case MSG_MEN_NAVIGATION_FIND_NEXT:
1572 DoSearch(SEARCH_NEXT);
1573 break;
1575 case MSG_MEN_NAVIGATION_FIND_PREV:
1576 DoSearch(SEARCH_PREV);
1577 break;
1579 case MSG_MEN_NAVIGATION_JUMP:
1580 Make_Goto_Requester();
1581 break;
1583 } /* switch(GTMENUITEM_USERDATA(item)) */
1585 men = item->NextSelect;
1586 } else {
1587 men = MENUNULL;
1590 } /* while(men != MENUNULL) */
1591 break;
1593 } /* switch(msg->Class) */
1595 ReplyMsg((struct Message *)msg);
1597 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1599 return quitme;
1602 /****************************************************************************************/
1604 static void HandleAll(void)
1606 ULONG sigs;
1607 LONG line;
1608 WORD search_kind;
1609 BOOL quitme = FALSE;
1611 in_main_loop = TRUE;
1613 ScreenToFront(win->WScreen);
1615 while(!quitme)
1617 sigs = Wait(msgmask | winmask | gotomask | findmask);
1619 if ( (sigs & winmask) || (sigs & msgmask) )
1620 quitme = HandleWin();
1622 if (sigs & gotomask)
1624 if (Handle_Goto_Requester(&line))
1626 ScrollTo(GAD_VERTSCROLL, line - 1, TRUE);
1630 if (sigs & findmask)
1632 if ((search_kind = Handle_Find_Requester(&searchtext)))
1634 DoSearch(search_kind);
1638 } /* while(!quitme) */
1641 /****************************************************************************************/
1643 int main(int argc, char **argv)
1645 int rc;
1647 /* This is for when Cleanup() is called */
1648 rc = setjmp(exit_buf);
1649 if (rc)
1650 return rc;
1652 InitLocale("System/Utilities/More.catalog", 2);
1653 InitMenus();
1654 GetArguments(argc, argv);
1655 OpenLibs();
1656 OpenFile();
1657 GetVisual();
1658 MakeGadgets();
1659 MakeMenus();
1660 MakeWin();
1661 HandleAll();
1662 Cleanup(0);
1663 return 0;
1666 /****************************************************************************************/