Tabs => space
[AROS.git] / workbench / utilities / More / more.c
blob20b0d020c6b81d7903d0c2c887914f2ef02a4b8b
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>
33 #include "global.h"
34 #include "req.h"
36 #define CATCOMP_NUMBERS
37 #include "strings.h"
39 #define DEBUG 0
40 #include <aros/debug.h>
42 static inline int abs(int x)
44 if (x < 0)
45 return -x;
46 return x;
49 static jmp_buf exit_buf;
51 /****************************************************************************************/
53 /* #define USE_WRITEMASK */
54 #define USE_SIMPLEREFRESH 0
56 #define DEFAULT_TABSIZE 8
58 #define INNER_SPACING_X 2
59 #define INNER_SPACING_Y 2
61 #define MAX_TEXTLINELEN 4096
63 #define ARG_TEMPLATE "FILE"
65 enum
67 ARG_FILE,
68 NUM_ARGS
71 enum
73 GAD_UPARROW,
74 GAD_DOWNARROW,
75 GAD_LEFTARROW,
76 GAD_RIGHTARROW,
77 GAD_VERTSCROLL,
78 GAD_HORIZSCROLL,
79 NUM_GADGETS
82 enum
84 IMG_UPARROW,
85 IMG_DOWNARROW,
86 IMG_LEFTARROW,
87 IMG_RIGHTARROW,
88 IMG_SIZE,
89 NUM_IMAGES
92 /****************************************************************************************/
94 struct LineNode
96 char *text;
97 UWORD stringlen;
98 UWORD textlen;
99 BOOL invert;
102 /****************************************************************************************/
104 struct IntuitionBase *IntuitionBase;
105 struct GfxBase *GfxBase;
106 struct Library *GadToolsBase;
107 struct Screen *scr;
108 struct DrawInfo *dri;
109 APTR vi;
110 struct Menu *menus;
111 struct Window *win;
112 struct MsgPort *msgport;
113 struct AppWindow *appwindow;
115 ULONG gotomask, findmask;
116 UBYTE filenamebuffer[300];
118 /****************************************************************************************/
120 static struct RastPort *rp;
121 static struct RDArgs *MyArgs;
123 static struct Gadget *gad[NUM_GADGETS], *firstgadget, *activearrowgad;
124 static struct Image *img[NUM_GADGETS];
126 static struct LineNode *linearray;
128 static UBYTE *filebuffer;
130 static char *filename, *fillename_dest, s[256], *searchtext;
132 static BPTR fh;
134 static UWORD tabsize = DEFAULT_TABSIZE;
136 static WORD fontwidth, fontheight, borderleft, bordertop;
137 static WORD shinepen, shadowpen, bgpen, textpen;
138 static WORD borderright, borderbottom, visiblex, visibley;
139 static WORD fontbaseline, textstartx, textstarty, textendx, textendy;
140 static WORD textwidth, textheight, viewstartx, viewstarty;
141 static WORD winwidth, winheight;
143 static ULONG winmask, msgmask;
144 static LONG filelen, num_lines, max_textlen;
145 static LONG search_startline, found_line = -1;
146 static WORD arrowticker;
148 static BOOL in_main_loop;
150 static IPTR Args[NUM_ARGS];
152 static BPTR oldlock = (BPTR)-1;
153 static BPTR parentlock = (BPTR)-1;
155 /*********************************************************************************************/
157 WORD ShowMessage(CONST_STRPTR title, CONST_STRPTR text, CONST_STRPTR gadtext)
159 struct EasyStruct es;
161 es.es_StructSize = sizeof(es);
162 es.es_Flags = 0;
163 es.es_Title = title;
164 es.es_TextFormat = text;
165 es.es_GadgetFormat = gadtext;
167 return EasyRequestArgs(win, &es, NULL, NULL);
170 /****************************************************************************************/
172 VOID Cleanup(CONST_STRPTR msg)
174 WORD rc, i;
176 if (msg)
178 if (IntuitionBase && !((struct Process *)FindTask(NULL))->pr_CLI)
180 ShowMessage("More", msg, MSG(MSG_OK));
181 } else {
182 Printf("More: %s\n", msg);
184 rc = RETURN_WARN;
185 } else {
186 rc = RETURN_OK;
189 CleanupRequesters();
191 KillMenus();
193 if (appwindow)
195 RemoveAppWindow(appwindow);
197 if (msgport)
199 DeleteMsgPort(msgport);
202 if (win)
204 for(i = 0; i < NUM_GADGETS;i++)
206 if (gad[i]) RemoveGadget(win, gad[i]);
209 CloseWindow(win);
212 for(i = 0; i < NUM_GADGETS;i++)
214 if (gad[i]) DisposeObject(gad[i]);
216 for(i = 0; i < NUM_IMAGES;i++)
218 if (img[i]) DisposeObject(img[i]);
221 if (vi) FreeVisualInfo(vi);
222 if (dri) FreeScreenDrawInfo(scr, dri);
223 if (scr) UnlockPubScreen(0, scr);
225 if (linearray) FreeVec(linearray);
226 if (filebuffer) FreeVec(filebuffer);
228 if (fh) Close(fh);
230 if (oldlock != (BPTR)-1) CurrentDir(oldlock);
232 if (GadToolsBase) CloseLibrary(GadToolsBase);
233 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
234 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
236 if (MyArgs) FreeArgs(MyArgs);
237 CleanupLocale();
239 longjmp(exit_buf, rc);
242 /****************************************************************************************/
244 static void DosError(void)
246 Fault(IoErr(), 0, s, 255);
247 if (in_main_loop)
249 ShowMessage("More", s, MSG(MSG_OK));
250 } else {
251 Cleanup(s);
255 /****************************************************************************************/
257 static void GetArguments(int argc, char **argv)
259 if (argc)
261 if (!(MyArgs = ReadArgs(ARG_TEMPLATE, Args, 0)))
263 DosError();
266 filename = (char *)Args[ARG_FILE];
268 else
270 struct WBStartup *startup = (struct WBStartup *) argv;
271 if (startup->sm_NumArgs > 1)
273 parentlock = startup->sm_ArgList[1].wa_Lock;
274 filename = startup->sm_ArgList[1].wa_Name;
275 if ((parentlock == BNULL) || (filename == NULL))
276 Cleanup(NULL);
278 oldlock = CurrentDir(parentlock);
282 if (!filename) filename = GetFile(TRUE);
283 if (!filename) Cleanup(NULL);
285 strncpy(filenamebuffer, filename, 299);
289 /****************************************************************************************/
291 static void OpenLibs(void)
293 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))
295 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "intuition.library", 39);
296 Cleanup(s);
299 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)))
301 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "graphics.library", 39);
302 Cleanup(s);
305 if (!(GadToolsBase = OpenLibrary("gadtools.library", 39)))
307 __sprintf(s, MSG(MSG_CANT_OPEN_LIB), "gadtools.library", 39);
308 Cleanup(s);
312 /****************************************************************************************/
314 static UWORD CalcTextLen(char *text)
316 char c;
317 UWORD rc = 0;
319 while((c = *text++))
321 if (c == '\t')
323 rc += tabsize;
324 } else {
325 rc++;
329 if (rc > MAX_TEXTLINELEN) rc = MAX_TEXTLINELEN;
331 return rc;
334 /****************************************************************************************/
336 static BOOL OpenFile(void)
338 struct LineNode *new_linearray;
339 UBYTE *new_filebuffer;
340 LONG new_filelen;
341 LONG new_num_lines;
343 struct LineNode *linepos;
344 UBYTE *filepos;
345 LONG flen, act_line;
347 BOOL seekable;
349 if (!(fh = Open(filename, MODE_OLDFILE)))
351 DosError();
352 return FALSE;
355 if (Seek(fh, 0, OFFSET_END) >= 0) {
356 new_filelen = Seek(fh, 0, OFFSET_BEGINNING);
357 seekable = TRUE;
359 else {
360 new_filelen = 0x10000;
361 seekable = FALSE;
364 if (new_filelen < 0)
366 Close(fh); fh = 0;
367 DosError();
368 return FALSE;
371 if (!(new_filebuffer = AllocVec(new_filelen + 1, MEMF_PUBLIC)))
373 Close(fh); fh = 0;
374 if (in_main_loop)
376 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
377 return FALSE;
379 Cleanup(MSG(MSG_NO_MEM));
382 if ((flen=Read(fh, new_filebuffer, new_filelen)) != new_filelen && seekable)
384 FreeVec(new_filebuffer);
385 Close(fh); fh = 0;
386 DosError();
387 return FALSE;
390 new_filelen = flen;
391 new_filebuffer[new_filelen] = '\0';
393 Close(fh);fh = 0;
395 filepos = new_filebuffer;
397 new_num_lines = 1;
399 while(flen--)
401 if (*filepos++ == '\n') new_num_lines++;
404 new_linearray = AllocVec(new_num_lines * sizeof(struct LineNode), MEMF_PUBLIC | MEMF_CLEAR);
405 if (!new_linearray)
407 FreeVec(new_filebuffer);
408 if (in_main_loop)
410 ShowMessage("More", MSG(MSG_NO_MEM), MSG(MSG_OK));
411 return FALSE;
413 Cleanup(MSG(MSG_NO_MEM));
416 linepos = new_linearray;
417 filepos = new_filebuffer;
419 act_line = 1;
420 max_textlen = 0;
421 while(act_line <= new_num_lines)
423 linepos->text = (char *)filepos;
425 while ((*filepos != '\n') && (*filepos != '\0'))
427 linepos->stringlen++; filepos++;
430 *filepos++ = '\0';
432 linepos->textlen = CalcTextLen(linepos->text);
433 if (linepos->textlen > max_textlen) max_textlen = linepos->textlen;
435 linepos++; act_line++;
438 if (filebuffer) FreeVec(filebuffer);
439 if (linearray) FreeVec(linearray);
441 filebuffer = new_filebuffer;
442 filelen = new_filelen;
443 linearray = new_linearray;
444 num_lines = new_num_lines;
446 return TRUE;
449 /****************************************************************************************/
451 static void GetVisual(void)
453 if (!(scr = LockPubScreen(0)))
455 Cleanup(MSG(MSG_CANT_LOCK_SCR));
458 if (!(dri = GetScreenDrawInfo(scr)))
460 Cleanup(MSG(MSG_CANT_GET_DRI));
463 if (!(vi = GetVisualInfoA(scr, 0)))
465 Cleanup(MSG(MSG_CANT_GET_VI));
468 shinepen = dri->dri_Pens[SHINEPEN];
469 shadowpen = dri->dri_Pens[SHADOWPEN];
470 textpen = dri->dri_Pens[TEXTPEN];
471 bgpen = dri->dri_Pens[BACKGROUNDPEN];
474 /****************************************************************************************/
476 static void MakeGadgets(void)
478 static WORD img2which[] =
480 UPIMAGE,
481 DOWNIMAGE,
482 LEFTIMAGE,
483 RIGHTIMAGE,
484 SIZEIMAGE
487 IPTR imagew[NUM_IMAGES], imageh[NUM_IMAGES];
488 WORD v_offset, h_offset, btop, i;
490 for(i = 0;i < NUM_IMAGES;i++)
492 img[i] = NewObject(0, SYSICLASS, SYSIA_DrawInfo , (Tag) dri,
493 SYSIA_Which , (Tag) img2which[i],
494 TAG_DONE);
496 if (!img[i]) Cleanup(MSG(MSG_CANT_CREATE_SYSIMAGE));
498 GetAttr(IA_Width, (Object *)img[i], &imagew[i]);
499 GetAttr(IA_Height, (Object *)img[i], &imageh[i]);
502 btop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;
504 v_offset = imagew[IMG_DOWNARROW] / 4;
505 h_offset = imageh[IMG_LEFTARROW] / 4;
507 firstgadget =
508 gad[GAD_UPARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_UPARROW] ,
509 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
510 GA_RelBottom , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
511 GA_ID , GAD_UPARROW ,
512 GA_RightBorder, TRUE ,
513 GA_Immediate , TRUE ,
514 GA_RelVerify , TRUE ,
515 TAG_DONE);
517 gad[GAD_DOWNARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_DOWNARROW] ,
518 GA_RelRight , -imagew[IMG_UPARROW] + 1 ,
519 GA_RelBottom , -imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ,
520 GA_ID , GAD_DOWNARROW ,
521 GA_RightBorder , TRUE ,
522 GA_Previous , (Tag)gad[GAD_UPARROW] ,
523 GA_Immediate , TRUE ,
524 GA_RelVerify , TRUE ,
525 TAG_DONE);
527 gad[GAD_VERTSCROLL] = NewObject(0, PROPGCLASS, GA_Top , btop + 1 ,
528 GA_RelRight , -imagew[IMG_DOWNARROW] + v_offset + 1 ,
529 GA_Width , imagew[IMG_DOWNARROW] - v_offset * 2 ,
530 GA_RelHeight , -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] - btop -2 ,
531 GA_ID , GAD_VERTSCROLL ,
532 GA_Previous , (Tag)gad[GAD_DOWNARROW] ,
533 GA_RightBorder , TRUE ,
534 GA_RelVerify , TRUE ,
535 GA_Immediate , TRUE ,
536 PGA_NewLook , TRUE ,
537 PGA_Borderless , TRUE ,
538 PGA_Total , 100 ,
539 PGA_Visible , 100 ,
540 PGA_Freedom , FREEVERT ,
541 TAG_DONE);
543 gad[GAD_RIGHTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_RIGHTARROW] ,
544 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] + 1,
545 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
546 GA_ID , GAD_RIGHTARROW ,
547 GA_BottomBorder , TRUE ,
548 GA_Previous , (Tag)gad[GAD_VERTSCROLL] ,
549 GA_Immediate , TRUE ,
550 GA_RelVerify , TRUE ,
551 TAG_DONE);
553 gad[GAD_LEFTARROW] = NewObject(0, BUTTONGCLASS, GA_Image , (Tag)img[IMG_LEFTARROW] ,
554 GA_RelRight , -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] - imagew[IMG_LEFTARROW] + 1,
555 GA_RelBottom , -imageh[IMG_RIGHTARROW] + 1 ,
556 GA_ID , GAD_LEFTARROW ,
557 GA_BottomBorder , TRUE ,
558 GA_Previous , (Tag)gad[GAD_RIGHTARROW] ,
559 GA_Immediate , TRUE ,
560 GA_RelVerify , TRUE ,
561 TAG_DONE);
563 gad[GAD_HORIZSCROLL] = NewObject(0, PROPGCLASS, GA_Left , scr->WBorLeft,
564 GA_RelBottom , -imageh[IMG_LEFTARROW] + h_offset + 1 ,
565 GA_RelWidth , -imagew[IMG_LEFTARROW] - imagew[IMG_RIGHTARROW] - imagew[IMG_SIZE] - scr->WBorRight - 2,
566 GA_Height , imageh[IMG_LEFTARROW] - (h_offset * 2) ,
567 GA_ID , GAD_HORIZSCROLL ,
568 GA_Previous , (Tag)gad[GAD_LEFTARROW] ,
569 GA_BottomBorder , TRUE ,
570 GA_RelVerify , TRUE ,
571 GA_Immediate , TRUE ,
572 PGA_NewLook , TRUE ,
573 PGA_Borderless , TRUE ,
574 PGA_Total , 100 ,
575 PGA_Visible , 100 ,
576 PGA_Freedom , FREEHORIZ ,
577 TAG_DONE);
579 for(i = 0;i < NUM_GADGETS;i++)
581 if (!gad[i]) Cleanup(MSG(MSG_CANT_CREATE_GADGET));
585 /****************************************************************************************/
587 static void CalcVisible(void)
589 visiblex = (win->Width - borderleft - borderright -
590 INNER_SPACING_X * 2) / fontwidth;
592 visibley = (win->Height - bordertop - borderbottom -
593 INNER_SPACING_Y * 2) / fontheight;
595 if (visiblex < 1) visiblex = 1;
596 if (visibley < 1) visibley = 1;
598 textendx = textstartx + visiblex * fontwidth - 1;
599 textendy = textstarty + visibley * fontheight - 1;
601 textwidth = textendx - textstartx + 1;
602 textheight = textendy - textstarty + 1;
605 /****************************************************************************************/
607 static void MySetAPen(struct RastPort *rp, LONG reg)
609 static LONG oldreg = -1;
611 if (reg != oldreg)
613 oldreg = reg;
614 SetAPen(rp, reg);
618 /****************************************************************************************/
620 static void MySetBPen(struct RastPort *rp, LONG reg)
622 static LONG oldreg = -1;
624 if (reg != oldreg)
626 oldreg = reg;
627 SetBPen(rp, reg);
631 /****************************************************************************************/
633 static void DrawTextLine(WORD viewline, WORD columns, BOOL clearright)
635 static char tempstring[MAX_TEXTLINELEN + 1];
636 static char c, *stringpos, *text;
637 LONG realline = viewline + viewstarty;
638 WORD textlen, i = 0, t, x;
639 BOOL inverted;
641 /* column < 0 means draw only first -column chars
643 ** column > 0 means draw only last column chars
645 ** column = 0 means draw whole line
648 if (columns != 0)
650 clearright = FALSE; /* because already cleared by ScrollRaster */
653 if ((viewline >= 0) && (viewline < visibley) &&
654 (realline >= 0) && (realline < num_lines))
656 inverted = linearray[realline].invert;
658 text = linearray[realline].text;
659 textlen = linearray[realline].textlen;
661 stringpos = tempstring;
663 while((c = *text++) && (i < textlen))
665 if (c == '\t')
667 for(t = 0; (t < tabsize) && (i < textlen);t++)
669 *stringpos++ = ' ';
670 i++;
672 } else {
673 *stringpos++ = c;
674 i++;
676 } /* while((c = *text++) && (i < textlen)) */
678 stringpos = tempstring + viewstartx;
679 i -= viewstartx;
681 if (i < 0)
683 i = 0;
684 } else {
685 if (i > visiblex) i = visiblex;
687 x = textstartx;
688 if (columns < 0)
690 if (i > (-columns)) i = (-columns);
691 } else if (columns > 0) {
692 x = textstartx + (visiblex - columns) * fontwidth;
693 stringpos += (visiblex - columns);
694 i -= (visiblex - columns);
697 if (i > 0)
699 MySetAPen(rp, textpen);
700 MySetBPen(rp, inverted ? shinepen : bgpen);
702 Move(rp, x,
703 textstarty + (viewline * fontheight) + fontbaseline);
705 Text(rp, stringpos, i);
709 } /* if ((realline >= 0) && (realline < num_lines)) */
711 if ((i < visiblex) && clearright)
713 MySetAPen(rp, bgpen);
714 RectFill(rp, textstartx + (i * fontwidth),
715 textstarty + (viewline * fontheight),
716 textendx,
717 textstarty + (viewline * fontheight) + fontheight - 1);
721 /****************************************************************************************/
723 static void DrawAllText(void)
725 WORD y;
727 for(y = 0;y < visibley;y++)
729 DrawTextLine(y, 0, TRUE);
733 /****************************************************************************************/
735 static void SetWinTitle(void)
737 static UBYTE wintitle[256];
738 BPTR lock;
740 strcpy(s, filename);
741 if ((lock = Lock(filename, SHARED_LOCK)))
743 NameFromLock(lock, s, 255);
744 UnLock(lock);
746 __sprintf(wintitle, MSG(MSG_WIN_TITLE), s, num_lines, filelen);
748 SetWindowTitles(win, wintitle, (UBYTE *)~0L);
751 /****************************************************************************************/
753 static void HandleFileChange(void)
755 strncpy(filenamebuffer, filename, 299);
756 SetWinTitle();
757 MySetAPen(rp, bgpen);
758 RectFill(rp, textstartx, textstarty, textendx, textendy);
760 CalcVisible();
762 viewstartx = viewstarty = 0;
764 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
765 PGA_Visible, visiblex ,
766 PGA_Total , max_textlen ,
767 TAG_DONE);
769 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
770 PGA_Visible , visibley ,
771 PGA_Total , num_lines ,
772 TAG_DONE);
773 DrawAllText();
777 /****************************************************************************************/
779 static void MakeWin(void)
781 if (!(win = OpenWindowTags(NULL, WA_PubScreen , (IPTR)scr ,
782 WA_Left , 0 ,
783 WA_Top , scr->BarHeight + 1 ,
784 WA_Width , 640 ,
785 WA_Height , 480 ,
786 WA_AutoAdjust , TRUE ,
787 USE_SIMPLEREFRESH ?
788 WA_SimpleRefresh :
789 TAG_IGNORE , TRUE ,
790 WA_CloseGadget , TRUE ,
791 WA_DepthGadget , TRUE ,
792 WA_DragBar , TRUE ,
793 WA_SizeGadget , TRUE ,
794 WA_SizeBBottom , TRUE ,
795 WA_SizeBRight , TRUE ,
796 WA_Activate , TRUE ,
797 WA_Gadgets , (IPTR)firstgadget ,
798 WA_MinWidth , 100 ,
799 WA_MinHeight , 100 ,
800 WA_MaxWidth , scr->Width ,
801 WA_MaxHeight , scr->Height ,
802 WA_ReportMouse , TRUE ,
803 WA_NewLookMenus , TRUE ,
804 WA_IDCMP , IDCMP_CLOSEWINDOW |
805 IDCMP_NEWSIZE |
806 IDCMP_GADGETDOWN |
807 IDCMP_GADGETUP |
808 IDCMP_MOUSEMOVE |
809 IDCMP_VANILLAKEY |
810 IDCMP_INTUITICKS |
811 (USE_SIMPLEREFRESH != 0) * IDCMP_REFRESHWINDOW |
812 IDCMP_RAWKEY |
813 IDCMP_MENUPICK ,
814 TAG_DONE)))
816 Cleanup(MSG(MSG_CANT_CREATE_WIN));
819 SetWinTitle();
821 winmask = 1L << win->UserPort->mp_SigBit;
823 if (!(msgport = CreateMsgPort()))
825 Cleanup(MSG(MSG_CANT_CREATE_MSGPORT));
827 if (!(appwindow = AddAppWindow(0,0,win,msgport,NULL)))
829 Cleanup(MSG(MSG_CANT_ADD_APPWINDOW));
831 msgmask = 1L << msgport->mp_SigBit;
833 winwidth = win->Width;
834 winheight = win->Height;
836 rp = win->RPort;
838 SetDrMd(rp, JAM2);
840 #ifdef USE_WRITEMASK
841 SetWriteMask(rp, 0x3);
842 #endif
844 fontwidth = rp->TxWidth;
845 fontheight = rp->TxHeight;
846 fontbaseline = rp->TxBaseline;
848 borderleft = win->BorderLeft;
849 bordertop = win->BorderTop;
850 borderright = win->BorderRight;
851 borderbottom = win->BorderBottom;
853 textstartx = borderleft + INNER_SPACING_X;
854 textstarty = bordertop + INNER_SPACING_Y;
856 CalcVisible();
858 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , 0 ,
859 PGA_Total , max_textlen ,
860 PGA_Visible , visiblex ,
861 TAG_DONE);
863 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , 0 ,
864 PGA_Total , num_lines ,
865 PGA_Visible , visibley ,
866 TAG_DONE);
868 DrawAllText();
870 SetMenuStrip(win, menus);
873 /****************************************************************************************/
875 static void NewWinSize(void)
877 WORD new_winwidth, new_winheight;
879 new_winwidth = win->Width;
880 new_winheight = win->Height;
882 CalcVisible();
884 if ((viewstartx + visiblex) > max_textlen)
886 viewstartx = max_textlen - visiblex;
887 if (viewstartx < 0) viewstartx = 0;
890 if ((viewstarty + visibley) > num_lines)
892 viewstarty = num_lines - visibley;
893 if (viewstarty < 0) viewstarty = 0;
896 SetGadgetAttrs(gad[GAD_HORIZSCROLL], win, 0, PGA_Top , viewstartx ,
897 PGA_Visible , visiblex ,
898 TAG_DONE);
900 SetGadgetAttrs(gad[GAD_VERTSCROLL], win, 0, PGA_Top , viewstarty ,
901 PGA_Visible , visibley ,
902 TAG_DONE);
904 if (new_winwidth < winwidth)
906 MySetAPen(rp, bgpen);
907 RectFill(rp, textendx + 1,
908 bordertop + INNER_SPACING_Y,
909 new_winwidth - borderright - 1,
910 new_winheight - borderbottom - 1);
913 if (new_winheight < winheight)
915 MySetAPen(rp, bgpen);
916 RectFill(rp, borderleft + INNER_SPACING_X,
917 textendy + 1,
918 new_winwidth - borderright - 1,
919 new_winheight - borderbottom - 1);
922 if ((new_winwidth > winwidth) ||
923 (new_winheight > winheight))
925 DrawAllText();
928 winwidth = new_winwidth;
929 winheight = new_winheight;
932 /****************************************************************************************/
934 #ifdef USE_SIMPLEREFRESH
936 /****************************************************************************************/
938 static void RefreshAll(void)
940 DrawAllText();
943 /****************************************************************************************/
945 static void HandleRefresh(void)
947 BeginRefresh(win);
948 RefreshAll();
949 EndRefresh(win, TRUE);
952 /****************************************************************************************/
954 #endif /* USE_SIMPLEREFRESH */
956 /****************************************************************************************/
958 static void ScrollTo(WORD gadid, LONG top, BOOL refreshprop)
960 LONG y, dx, dy;
962 MySetBPen(rp, bgpen);
964 switch(gadid)
966 case GAD_VERTSCROLL:
967 if (top + visibley > num_lines)
969 top = num_lines - visibley;
971 if (top < 0) top = 0;
973 if (top != viewstarty )
975 dy = top - viewstarty;
976 viewstarty = top;
978 if (refreshprop)
980 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstarty,
981 TAG_DONE);
984 if (abs(dy) >= visibley)
986 DrawAllText();
987 } else {
988 if (dy > 0)
991 #ifdef USE_SIMPLEREFRESH
992 ScrollRaster(rp,
994 fontheight * dy,
995 textstartx,
996 textstarty,
997 textendx,
998 textendy);
1000 if (rp->Layer->Flags & LAYERREFRESH)
1002 HandleRefresh();
1004 #else
1005 ClipBlit(rp, textstartx,
1006 textstarty + dy * fontheight,
1007 rp, textstartx,
1008 textstarty,
1009 textwidth,
1010 textheight - dy * fontheight,
1011 192);
1012 #endif
1014 for (y = visibley - dy;y < visibley;y++)
1016 DrawTextLine(y, 0, TRUE);
1018 } else {
1019 dy = -dy;
1021 #ifdef USE_SIMPLEREFRESH
1022 ScrollRaster(rp,
1024 -fontheight * dy,
1025 textstartx,
1026 textstarty,
1027 textendx,
1028 textendy);
1030 if (rp->Layer->Flags & LAYERREFRESH)
1032 HandleRefresh();
1035 #else
1036 ClipBlit(rp, textstartx,
1037 textstarty,
1038 rp, textstartx,
1039 textstarty + dy * fontheight,
1040 textwidth,
1041 textheight - dy * fontheight,
1042 192);
1043 #endif
1044 for (y = 0;y < dy;y++)
1046 DrawTextLine(y, 0, TRUE);
1051 } /* if (top != viewstarty ) */
1052 break;
1054 case GAD_HORIZSCROLL:
1055 if (top + visiblex > max_textlen)
1057 top = max_textlen - visiblex;
1059 if (top < 0) top = 0;
1061 if (top != viewstartx )
1063 dx = top - viewstartx;
1064 viewstartx = top;
1066 if (refreshprop)
1068 SetGadgetAttrs(gad[gadid], win, 0, PGA_Top , viewstartx,
1069 TAG_DONE);
1072 if (abs(dx) >= visiblex)
1074 DrawAllText();
1075 } else {
1076 if (dx > 0)
1079 #ifdef USE_SIMPLEREFRESH
1080 ScrollRaster(rp,
1081 fontwidth * dx,
1083 textstartx,
1084 textstarty,
1085 textendx,
1086 textendy);
1088 if (rp->Layer->Flags & LAYERREFRESH)
1090 HandleRefresh();
1092 #else
1093 ClipBlit(rp, textstartx + dx * fontwidth,
1094 textstarty,
1095 rp, textstartx,
1096 textstarty,
1097 textwidth - dx * fontwidth,
1098 textheight,
1099 192);
1100 #endif
1101 for (y = 0;y < visibley;y++)
1103 DrawTextLine(y, dx, TRUE);
1106 } else {
1107 dx = -dx;
1109 #ifdef USE_SIMPLEREFRESH
1110 ScrollRaster(rp,
1111 -fontwidth * dx,
1113 textstartx,
1114 textstarty,
1115 textendx,
1116 textendy);
1118 if (rp->Layer->Flags & LAYERREFRESH)
1120 HandleRefresh();
1123 #else
1124 ClipBlit(rp, textstartx,
1125 textstarty,
1126 rp, textstartx + dx * fontwidth,
1127 textstarty,
1128 textwidth - dx * fontwidth,
1129 textheight,
1130 192);
1131 #endif
1132 for (y = 0;y < visibley;y++)
1134 DrawTextLine(y, -dx, TRUE);
1139 } /* if (top != viewstartx ) */
1140 break;
1142 } /* switch(gadid) */
1146 /****************************************************************************************/
1148 static void HandleScrollGadget(WORD gadid)
1150 struct IntuiMessage *msg;
1151 IPTR top;
1152 BOOL ok=FALSE;
1154 while (!ok)
1156 WaitPort(win->UserPort);
1157 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1159 switch (msg->Class)
1161 case IDCMP_GADGETUP:
1162 ok=TRUE;
1163 /* fall through */
1165 case IDCMP_MOUSEMOVE:
1166 GetAttr(PGA_Top, (Object *)gad[gadid], &top);
1167 ScrollTo(gadid, top, FALSE);
1168 break;
1170 #ifdef USE_SIMPLEREFRESH
1171 case IDCMP_REFRESHWINDOW:
1172 HandleRefresh();
1173 break;
1174 #endif
1176 } /* switch (msg->Class) */
1177 ReplyMsg((struct Message *)msg);
1179 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1181 } /* while (!ok) */
1184 /****************************************************************************************/
1186 static BOOL FindString(struct LineNode *ln, char *search, LONG searchlen)
1188 char *text = ln->text;
1189 LONG textlen = ln->stringlen;
1190 LONG i;
1191 BOOL rc = FALSE;
1193 textlen -= searchlen;
1195 while(textlen >= 0)
1197 for(i = 0;i < searchlen;i++)
1199 if (ToUpper(text[i]) != ToUpper(search[i])) break;
1202 if (i == searchlen)
1204 rc = TRUE;
1205 break;
1207 text++;textlen--;
1210 return rc;
1213 /****************************************************************************************/
1215 static void DoSearch(WORD kind)
1217 LONG line, searchlen;
1218 BOOL done = FALSE;
1220 if (!searchtext) return;
1222 searchlen = strlen(searchtext);
1223 if (searchlen == 0) return;
1225 line = search_startline;
1227 if (kind == SEARCH_NEXT && line < num_lines - 1)
1228 line++;
1229 else if (kind == SEARCH_PREV && line > 0)
1230 line--;
1232 if (kind == SEARCH_NEW)
1234 line = 0;
1235 kind = SEARCH_NEXT;
1238 while(!done)
1240 if (FindString(&linearray[line], searchtext, searchlen))
1242 done = TRUE;
1243 if (found_line >= 0)
1245 linearray[found_line].invert = FALSE;
1246 DrawTextLine(found_line - viewstarty, 0, TRUE);
1249 ScrollTo(GAD_VERTSCROLL, line - visibley / 2, TRUE);
1251 found_line = line;
1252 search_startline = line;
1253 linearray[found_line].invert = TRUE;
1254 DrawTextLine(found_line - viewstarty, 0, TRUE);
1257 if (kind == SEARCH_NEXT)
1259 line++;
1260 if (line >= num_lines)
1262 done = TRUE;
1263 DisplayBeep(NULL);
1265 } else {
1266 line--;
1267 if (line < 0)
1269 done = TRUE;
1270 DisplayBeep(NULL);
1274 } /* while(!done) */
1278 /****************************************************************************************/
1280 static BOOL HandleWin(void)
1282 struct IntuiMessage *msg;
1283 struct MenuItem *item;
1284 WORD gadid, delta;
1285 UWORD men, code;
1286 UBYTE key;
1287 BOOL pagescroll, maxscroll, quitme = FALSE;
1288 TEXT editorvarbuffer[300];
1289 struct AppMessage *appmsg;
1290 //struct WBArg *argptr;
1292 while ((appmsg = (struct AppMessage *) GetMsg(msgport)))
1294 if (appmsg->am_Type == AMTYPE_APPWINDOW)
1296 if (appmsg->am_NumArgs >= 1)
1298 NameFromLock(appmsg->am_ArgList->wa_Lock, filenamebuffer, 299);
1299 AddPart(filenamebuffer, appmsg->am_ArgList->wa_Name, 299);
1300 filename = filenamebuffer;
1301 D(bug("[More] appwindow received message: filename = %s\n", filename));
1305 ReplyMsg ((struct Message *) appmsg);
1306 ActivateWindow(win);
1308 if (OpenFile())
1309 HandleFileChange();
1311 } /* while ((appmsg = (struct AppMessage *) GetMsg(msgport))) */
1313 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
1315 switch(msg->Class)
1317 case IDCMP_CLOSEWINDOW:
1318 quitme = TRUE;
1319 break;
1321 case IDCMP_NEWSIZE:
1322 NewWinSize();
1323 break;
1325 #ifdef USE_SIMPLEREFRESH
1326 case IDCMP_REFRESHWINDOW:
1327 HandleRefresh();
1328 break;
1329 #endif
1330 case IDCMP_GADGETDOWN:
1331 gadid = ((struct Gadget *)msg->IAddress)->GadgetID;
1332 arrowticker = 3;
1334 switch(gadid)
1336 case GAD_HORIZSCROLL:
1337 case GAD_VERTSCROLL:
1338 HandleScrollGadget(gadid);
1339 break;
1341 case GAD_UPARROW:
1342 activearrowgad = (struct Gadget *)msg->IAddress;
1343 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1344 break;
1346 case GAD_DOWNARROW:
1347 activearrowgad = (struct Gadget *)msg->IAddress;
1348 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1349 break;
1351 case GAD_LEFTARROW:
1352 activearrowgad = (struct Gadget *)msg->IAddress;
1353 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1354 break;
1356 case GAD_RIGHTARROW:
1357 activearrowgad = (struct Gadget *)msg->IAddress;
1358 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1359 break;
1361 break;
1363 case IDCMP_INTUITICKS:
1364 if (activearrowgad)
1366 if (arrowticker)
1368 arrowticker--;
1370 else if (activearrowgad->Flags & GFLG_SELECTED)
1372 switch(activearrowgad->GadgetID)
1374 case GAD_UPARROW:
1375 ScrollTo(GAD_VERTSCROLL, viewstarty - 1, TRUE);
1376 break;
1378 case GAD_DOWNARROW:
1379 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1380 break;
1382 case GAD_LEFTARROW:
1383 ScrollTo(GAD_HORIZSCROLL, viewstartx - 1, TRUE);
1384 break;
1386 case GAD_RIGHTARROW:
1387 ScrollTo(GAD_HORIZSCROLL, viewstartx + 1, TRUE);
1388 break;
1392 break;
1394 case IDCMP_GADGETUP:
1395 activearrowgad = NULL;
1396 break;
1398 case IDCMP_VANILLAKEY:
1399 key = ToUpper(msg->Code);
1400 if (key == 27)
1402 quitme = TRUE;
1404 else if (key == 8 || (key == ' ' && (0 != (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)))))
1406 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1408 else if (key == ' ')
1410 ScrollTo(GAD_VERTSCROLL, viewstarty + visibley - 1, TRUE);
1412 else if (key == 13)
1414 ScrollTo(GAD_VERTSCROLL, viewstarty + 1, TRUE);
1416 else if (strchr(MSG(MSG_SHORTCUT_TOP), key))
1418 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1420 else if (strchr(MSG(MSG_SHORTCUT_BOTTOM), key))
1422 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1424 else if (strchr(MSG(MSG_SHORTCUT_JUMP), key))
1426 Make_Goto_Requester();
1428 else if (strchr(MSG(MSG_SHORTCUT_FIND), key))
1430 Make_Find_Requester();
1432 else if (strchr(MSG(MSG_SHORTCUT_NEXT), key))
1434 DoSearch(SEARCH_NEXT);
1436 else if (strchr(MSG(MSG_SHORTCUT_PREV), key))
1438 DoSearch(SEARCH_PREV);
1440 else if (strchr(MSG(MSG_SHORTCUT_EDITOR), key))
1442 if ( (GetVar("editor", editorvarbuffer, 299, GVF_GLOBAL_ONLY)) != -1L )
1444 __sprintf(s, "Run QUIET \"%s\" \"%s\"", editorvarbuffer, filenamebuffer );
1445 if (SystemTags(s, TAG_END))
1446 DisplayBeep(NULL);
1449 break;
1451 case IDCMP_RAWKEY:
1452 pagescroll = (0 != (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)));
1453 maxscroll = (0 != (msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT | IEQUALIFIER_CONTROL)));
1455 code = msg->Code; delta = 1;
1457 switch(code)
1459 case RAWKEY_NM_WHEEL_UP:
1460 code = CURSORUP;
1461 delta = 3;
1462 break;
1464 case RAWKEY_NM_WHEEL_DOWN:
1465 code = CURSORDOWN;
1466 delta = 3;
1467 break;
1469 case RAWKEY_NM_WHEEL_LEFT:
1470 code = CURSORLEFT;
1471 delta = 3;
1472 break;
1474 case RAWKEY_NM_WHEEL_RIGHT:
1475 code = CURSORRIGHT;
1476 delta = 3;
1477 break;
1480 switch(code)
1482 case CURSORUP:
1483 ScrollTo(GAD_VERTSCROLL,
1484 maxscroll ? 0 : viewstarty - (pagescroll ? visibley - 1 : delta),
1485 TRUE);
1486 break;
1488 case CURSORDOWN:
1489 ScrollTo(GAD_VERTSCROLL,
1490 maxscroll ? num_lines : viewstarty + (pagescroll ? visibley - 1 : delta),
1491 TRUE);
1492 break;
1494 case CURSORLEFT:
1495 ScrollTo(GAD_HORIZSCROLL,
1496 maxscroll ? 0 : viewstartx - (pagescroll ? visiblex - 1 : delta),
1497 TRUE);
1498 break;
1500 case CURSORRIGHT:
1501 ScrollTo(GAD_HORIZSCROLL,
1502 maxscroll ? max_textlen : viewstartx + (pagescroll ? visiblex - 1 : delta),
1503 TRUE);
1504 break;
1506 case RAWKEY_HOME:
1507 ScrollTo(GAD_VERTSCROLL, 0, TRUE);
1508 break;
1510 case RAWKEY_END:
1511 ScrollTo(GAD_VERTSCROLL, num_lines, TRUE);
1512 break;
1514 case RAWKEY_PAGEUP:
1515 ScrollTo(GAD_VERTSCROLL, viewstarty - (visibley - 1), TRUE);
1516 break;
1518 case RAWKEY_PAGEDOWN:
1519 ScrollTo(GAD_VERTSCROLL, viewstarty + (visibley - 1), TRUE);
1520 break;
1522 } /* switch(msg->Code) */
1523 break;
1525 case IDCMP_MENUPICK:
1526 men = msg->Code;
1527 while(men != MENUNULL)
1529 if ((item = ItemAddress(menus, men)))
1531 switch((IPTR)GTMENUITEM_USERDATA(item))
1533 case MSG_MEN_PROJECT_SAVEAS:
1534 fillename_dest = GetFile(FALSE);
1535 if (!fillename_dest)
1536 break;
1538 case MSG_MEN_PROJECT_PRINT:
1539 __sprintf(s, "Run >NIL: Type \"%s\" TO \"%s\"", filenamebuffer, fillename_dest ? fillename_dest : "PRT:");
1540 if (System(s, TAG_END))
1541 DisplayBeep(NULL);
1542 fillename_dest = NULL;
1543 break;
1545 case MSG_MEN_PROJECT_ABOUT:
1546 About();
1547 break;
1549 case MSG_MEN_PROJECT_QUIT:
1550 quitme = TRUE;
1551 break;
1553 case MSG_MEN_PROJECT_OPEN:
1554 if ((filename = GetFile(TRUE)))
1556 if (OpenFile())
1558 HandleFileChange();
1559 } /* if (OpenFile()) */
1561 } /* if ((filename = GetFile())) */
1563 break;
1565 case MSG_MEN_NAVIGATION_FIND:
1566 Make_Find_Requester();
1567 break;
1569 case MSG_MEN_NAVIGATION_FIND_NEXT:
1570 DoSearch(SEARCH_NEXT);
1571 break;
1573 case MSG_MEN_NAVIGATION_FIND_PREV:
1574 DoSearch(SEARCH_PREV);
1575 break;
1577 case MSG_MEN_NAVIGATION_JUMP:
1578 Make_Goto_Requester();
1579 break;
1581 } /* switch(GTMENUITEM_USERDATA(item)) */
1583 men = item->NextSelect;
1584 } else {
1585 men = MENUNULL;
1588 } /* while(men != MENUNULL) */
1589 break;
1591 } /* switch(msg->Class) */
1593 ReplyMsg((struct Message *)msg);
1595 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1597 return quitme;
1600 /****************************************************************************************/
1602 static void HandleAll(void)
1604 ULONG sigs;
1605 LONG line;
1606 WORD search_kind;
1607 BOOL quitme = FALSE;
1609 in_main_loop = TRUE;
1611 ScreenToFront(win->WScreen);
1613 while(!quitme)
1615 sigs = Wait(msgmask | winmask | gotomask | findmask);
1617 if ( (sigs & winmask) || (sigs & msgmask) )
1618 quitme = HandleWin();
1620 if (sigs & gotomask)
1622 if (Handle_Goto_Requester(&line))
1624 ScrollTo(GAD_VERTSCROLL, line - 1, TRUE);
1628 if (sigs & findmask)
1630 if ((search_kind = Handle_Find_Requester(&searchtext)))
1632 DoSearch(search_kind);
1636 } /* while(!quitme) */
1639 /****************************************************************************************/
1641 int main(int argc, char **argv)
1643 int rc;
1645 /* This is for when Cleanup() is called */
1646 rc = setjmp(exit_buf);
1647 if (rc)
1648 return rc;
1650 InitLocale("System/Utilities/More.catalog", 1);
1651 InitMenus();
1652 GetArguments(argc, argv);
1653 OpenLibs();
1654 OpenFile();
1655 GetVisual();
1656 MakeGadgets();
1657 MakeMenus();
1658 MakeWin();
1659 HandleAll();
1660 Cleanup(0);
1661 return 0;
1664 /****************************************************************************************/