home *** CD-ROM | disk | FTP | other *** search
- #include "snap.h"
-
- #define COPY 0xC0L
- #define INVCOPY 0x30L
- #define CopyChar(_x, _y, _m) \
- BltBitMap(&MyBM, (LONG)_x, (LONG)_y, \
- &TempBM, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, \
- _m, -1L, NULL); \
- WaitBlit()
-
- WORD Unit;
- IMPORT WORD StartUnit;
-
- LONG xl; /* leftmost x position */
- LONG xr; /* rightmost x position */
- LONG yt; /* topmost y position */
- LONG yb; /* bottommost y position */
- LONG minx; /* left limit */
- LONG maxx; /* right limit */
- LONG tl, tr; /* used by findword - left and right edge of word */
-
- LONG mx, my; /* Mouse position in character steps */
- #define closetop 0
- #define closebottom 1
- WORD closey;
- #define closeleft 0
- #define closeright 1
- WORD closex;
-
-
- struct Window *window; /* The window we're snapping from */
-
- /* Data for font being snapped */
- UWORD FontHeight;
- UBYTE FontType;
- UWORD FontWidth;
- UBYTE LoChar;
- UBYTE HiChar;
- UWORD Modulo;
- UWORD *CharLoc;
- UWORD NoOfChars;
- UBYTE *SrcData;
- IMPORT UBYTE *CharData;
-
- IMPORT struct RastPort TempRp, MyRP;
- IMPORT struct BitMap TempBM, MyBM;
- IMPORT WORD FrameMask;
-
- IMPORT UWORD *TempRaster; /* Used for character recognition */
-
- IMPORT struct Screen *theScreen;
- IMPORT struct Layer_Info *LockedLayerInfo;
- IMPORT struct RastPort rp;
- IMPORT UWORD CrawlPtrn;
-
- IMPORT LONGBITS cancelsignal, donesignal, movesignal, clicksignal, timersignal;
- IMPORT WORD action;
-
- WORD starting;
-
- /* Init vars with font data.
- */
-
- VOID SetSnapFont(font)
- struct TextFont *font;
- {
- if (!font) {
- FontWidth = -1;
- return;
- }
- FontHeight = font->tf_YSize;
- FontType = font->tf_Flags;
- FontWidth = (FontType & FPF_PROPORTIONAL ? -1 : font->tf_XSize);
- if (FontWidth == -1) {
- return;
- }
- LoChar = font->tf_LoChar;
- HiChar = font->tf_HiChar;
- Modulo = font->tf_Modulo;
- CharLoc = (UWORD *)font->tf_CharLoc;
- NoOfChars = HiChar-LoChar+1;
- Modulo = font->tf_Modulo;
- SrcData = (UBYTE *)font->tf_CharData;
- BltClear(CharData, 224L*32, 0L);
- WaitBlit();
- CopyFont();
- }
-
- /* Check if the character at x, y is a space
- */
-
- WORD IsSpace(x, y)
- LONG x, y;
- {
- REGISTER WORD i = FontHeight-1;
- REGISTER UWORD *data = &TempRaster[i];
-
- /* Copy character at x, y */
- BltClear(TempRaster, 32L, 0L);
- ClipBlit(&rp, x, y,
- &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, COPY);
- WaitBlit();
-
- if (*data) { /* Try inverted copy */
- ClipBlit(&rp, x, y,
- &TempRp, 0L, 0L, (LONG)FontWidth, (LONG)FontHeight, INVCOPY);
- WaitBlit();
- }
- while (i--) {
- if (*data--) {
- return 0;
- }
- }
- return 1;
- }
-
- #define ShortFrame 4L /* Square frame - columnar select */
- #define LongFrame 8L /* Strange frame - char or word select */
- IMPORT LONG OFType; /* Old frame type: ShortFrame/LongFrame */
- IMPORT UWORD Ptrn;
- IMPORT Point OldFrame[];
- IMPORT Point NewFrame[];
-
-
- /* update_frame calculates the new frame,
- ** erases the old frame and draws the new one.
- ** It's all pretty obvious if you take it slowly.
- */
- VOID update_frame()
- {
- LONG ft;
- switch (Unit) {
- case UNIT_FRAME: {
- /*********\
- * *
- * *
- \*********/
- NewFrame[0].x = xl-1; NewFrame[0].y = yt-1;
- NewFrame[1].x = xr+FontWidth; NewFrame[1].y = yt-1;
- NewFrame[2].x = xr+FontWidth; NewFrame[2].y = yb+FontHeight;
- NewFrame[3].x = xl-1; NewFrame[3].y = yb+FontHeight;
- NewFrame[4].x = xl-1; NewFrame[4].y = yt-1;
- ft = ShortFrame;
- break;
- }
- case UNIT_CHAR:
- case UNIT_WORD: {
- if (yt == yb) { /* On the same line - same as UNIT_FRAME */
- NewFrame[0].x = xl-1; NewFrame[0].y = yt-1;
- NewFrame[1].x = xr+FontWidth; NewFrame[1].y = yt-1;
- NewFrame[2].x = xr+FontWidth; NewFrame[2].y = yb+FontHeight;
- NewFrame[3].x = xl-1; NewFrame[3].y = yb+FontHeight;
- NewFrame[4].x = xl-1; NewFrame[4].y = yt-1;
- ft = ShortFrame;
- } else {
- /*****\
- ****** *
- * *
- * *****
- *******/
- NewFrame[0].x = xl-1; NewFrame[0].y = yt-1;
- NewFrame[1].x = maxx+FontWidth; NewFrame[1].y = yt-1;
- NewFrame[2].x = maxx+FontWidth; NewFrame[2].y = yb;
- NewFrame[3].x = xr+FontWidth; NewFrame[3].y = yb;
- NewFrame[4].x = xr+FontWidth; NewFrame[4].y = yb+FontHeight;
- NewFrame[5].x = minx-1; NewFrame[5].y = yb+FontHeight;
- NewFrame[6].x = minx-1; NewFrame[6].y = yt+FontHeight;
- NewFrame[7].x = xl-1; NewFrame[7].y = yt+FontHeight;
- NewFrame[8].x = xl-1; NewFrame[8].y = yt-1;
- ft = LongFrame;
- }
- break;
- }
- case UNIT_LINE: {
- NewFrame[0].x = minx-1; NewFrame[0].y = yt-1;
- NewFrame[1].x = maxx+FontWidth; NewFrame[1].y = yt-1;
- NewFrame[2].x = maxx+FontWidth; NewFrame[2].y = yb+FontHeight;
- NewFrame[3].x = minx-1; NewFrame[3].y = yb+FontHeight;
- NewFrame[4].x = minx-1; NewFrame[4].y = yt-1;
- ft = ShortFrame;
- break;
- }
- default: {
- break;
- }
- }
- draw_frame(ft);
- }
-
- VOID FindWord()
- {
- /* Must remove frame to be able to search for spaces */
- WaitTOF();
- erase_frame();
- tl = mx;
- /* Find a space to the left... */
- while (!IsSpace(tl, my)) {
- tl -= FontWidth;
- if (tl < minx) {
- break;
- }
- }
- tl += FontWidth;
- tr = mx;
- /* ...and to the right */
- while (!IsSpace(tr, my)) {
- tr += FontWidth;
- if (tr+FontWidth > maxx) {
- break;
- }
- }
- tr -= FontWidth;
- if (tr < tl) {
- tl = xl;
- tr = xr;
- }
- }
-
- /* ChangeUnit cycles the unit of selection. The differents units
- are: character, word and line.
- */
-
- VOID ChangeUnit()
- {
-
- switch (Unit) {
- case UNIT_FRAME: {
- Unit = UNIT_CHAR;
- break;
- }
- case UNIT_CHAR: {
- Unit = UNIT_WORD;
- FindWord();
- xl = tl;
- xr = tr;
- break;
- }
- case UNIT_WORD: {
- Unit = UNIT_LINE;
- xl = minx;
- xr = maxx;
- break;
- }
- case UNIT_LINE: {
- Unit = UNIT_FRAME;
- xl = xr = mx;
- break;
- }
- }
- }
-
- /* ExtendSelection extends the current selection according to
- the mouse position and the selected unit.
- Note that ExtendSelection doesn't optimize moves that don't
- make any difference. FIXME
- */
-
- VOID ExtendSelection()
- {
- /* Fix which row we're talking about */
- if (closey == closetop) { /* Find closest row */
- yt = my; /* change top row */
- } else {
- yb = my; /* change bottom row */
- }
-
- /* Take care of left and right character pos */
- switch (Unit) {
- case UNIT_FRAME: {
- if (closex == closeleft) {
- xl = mx;
- } else {
- xr = mx;
- }
- break;
- }
- case UNIT_CHAR: {
- if (yt == yb) { /* One line */
- if (closex == closeleft) {
- xl = mx;
- } else {
- xr = mx;
- }
- } else { /* Multiple lines */
- if (yt == my) {
- xl = mx; /* At top - set left */
- } else {
- xr = mx; /* At bottom - set right */
- }
- }
- break;
- }
- case UNIT_WORD: {
- FindWord(mx, my); /* Find the word */
- if (yt == yb) { /* One line */
- if (closex == closeleft) { /* Find closest char pos */
- xl = tl;
- } else {
- xr = tr;
- }
- } else { /* Multiple lines */
- if (yt == my) { /* Where am I */
- xl = tl; /* At top - set left */
- } else {
- xr = tr; /* At bottom - set right */
- }
- }
- break;
- }
- case UNIT_LINE: { /* Always full width */
- break;
- }
- }
- if (yt-FontHeight == yb) {
- yb += FontHeight;
- }
- if (yt == yb && xl-FontWidth == xr) {
- xr += FontWidth;
- }
- if (xr > maxx) { /* Check for window bounds */
- xr = maxx;
- }
- if (xl < minx) { /* Check for window bounds */
- xl = minx;
- }
- }
-
- /* The actual character snapper. It actually works. */
-
- WORD SnapChars()
- {
- REGISTER struct RastPort MyRastPort;
- LONG width;
- LONG height;
- UBYTE *SnapSpace;
- ULONG SnapSize;
- ULONG counter;
- REGISTER LONG x, y;
-
- /* Check coordinates */
- if (yt-FontHeight == yb) { /* No rows, shouldn't happen */
- return 0;
- }
- if (yt == yb && xl-FontWidth == xr) { /* Nothing at all */
- return 0;
- }
-
- /* Calculate stuff */
- width = maxx - (minx+1) + FontWidth+FontWidth; /* Add one for a LF */
- height = yb - yt + FontHeight;
- SnapSize = ((width/FontWidth)+1) * (height/FontHeight);
- counter = 0;
-
- /* Initialize things */
- InitRastPort(&MyRP);
- InitBitMap(&MyBM, 1L, width, height);
- MyRP.BitMap = &MyBM;
- SnapSpace = AllocMem(SnapSize, MEMF_PUBLIC|MEMF_CLEAR);
- /* Please insert more memory */
- if (!SnapSpace) {
- return 0;
- }
- MyBM.Planes[0] = AllocRaster(width, height);
- if (!MyBM.Planes[0]) {
- FreeMem(SnapSpace, SnapSize);
- return 0;
- }
- /* Make a local copy of the snapped chars */
- ClipBlit(&rp, minx, yt, &MyRP, 0L, 0L, width, height, COPY);
-
- /* Ok, now we've got a copy of the character data */
- /* Now it's ok to mess with the layers again */
- UnlockLayers(LockedLayerInfo);
-
- /* Clear our work area */
- BltClear(TempRaster, 32L, 0L);
-
- /* Calculate bounds */
- xl -= minx;
- xr -= minx;
- maxx -= minx;
- minx = 0;
- yb -= yt;
- yt = 0;
-
- /* Single line - needs to be handled separately */
- if (yt == yb) { /* Ok, we've got one */
-
- /* Read from left to right */
- for (x=xl; x<=xr; x+=FontWidth, counter++) {
- CopyChar(x, yt, COPY);
- if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- SnapSpace[counter] = 63; /* Unrecognized changed to ? */
- }
- }
- } else { /* Multiple lines */
-
- if (Unit == UNIT_FRAME) {
- minx = xl;
- maxx = xr;
- }
-
- /* Read first line */
- for (x=xl; x<=maxx; x+=FontWidth, counter++) {
- CopyChar(x, yt, COPY);
- if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- SnapSpace[counter] = 63; /* Unrecognized changed to ? */
- }
- }
- if (Unit == UNIT_FRAME) {
- SnapSpace[counter++] = 10;
- } else {
- /* Remove trailing blanks */
- while (counter && SnapSpace[counter-1] == ' ') {
- counter--;
- }
- SnapSpace[counter++] = 10;
- }
-
- /* If more than two rows - read full middle rows */
- if (yt+FontHeight != yb) {
- for (y=yt+FontHeight; y<yb; y+=FontHeight) {
- for (x=minx; x<=maxx; x+=FontWidth, counter++) {
- CopyChar(x, y, COPY);
- if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- SnapSpace[counter] = 63; /* Unrecognized - ? */
- }
- }
- if (Unit == UNIT_FRAME) {
- SnapSpace[counter++] = 10;
- } else {
- /* Remove trailing blanks */
- while (counter && SnapSpace[counter-1] == ' ') {
- counter--;
- }
- SnapSpace[counter++] = 10;
- }
- }
- }
-
- /* Read last line */
- for (x=minx; x<=xr; x+=FontWidth, counter++) {
- CopyChar(x, yb, COPY);
- if ((SnapSpace[counter] = interpret(TempRaster)) == 255) {
- SnapSpace[counter] = 63; /* Unrecognized changed to ? */
- }
- }
- /* Remove trailing blanks */
- while (counter && SnapSpace[counter-1] == ' ') {
- counter--;
- }
- }
- FreeRaster(MyBM.Planes[0], width, height);
- SaveClip(SnapSpace, counter);
- FreeMem(SnapSpace, SnapSize);
- return 1;
- }
-
-
- /* HandleChars is the part of the Snap state machine that handles
- snapping of characters. The selection is done in different
- units: char, word, line.
- */
-
- WORD HandleChars()
- {
- LONG xoff, yoff;
- LONG ox, oy;
-
- /* Find out which screen we're working on */
- theScreen = WhichScreen();
-
- /* Oops, no screen? */
- if (!theScreen) {
- action = noaction;
- return 0;
- }
-
- /* Ok, what window? */
- window = WhichWindow(theScreen);
-
- /* Oh dear, no window. */
- if (!window) {
- action = noaction;
- return 0;
- }
-
- /* No messing with the layers while I think */
- LockedLayerInfo = &window->WScreen->LayerInfo;
- LockLayers(LockedLayerInfo);
-
- /* Don't want to wreck somebody's rastport */
- CopyMem(window->RPort, &rp, (long)sizeof(struct RastPort));
-
- /* Or his picture */
- SetDrMd(&rp, COMPLEMENT);
- rp.Mask = FrameMask;
- Ptrn = CrawlPtrn;
- SetDrPt(&rp, Ptrn);
-
- /* Find out what we're trying to read */
- SetSnapFont(rp.Font);
- if (FontWidth == -1) {
- UnlockLayers(LockedLayerInfo);
- action = noaction;
- return 0;
- }
-
- /* Find a position */
- xl = window->MouseX - 7;
- yt = window->MouseY - 7;
-
- if (xl<0) {
- xl = 0;
- }
- if (yt<0) {
- yt = 0;
- }
-
- /* Check your position */
- if (xl>window->Width || yt>window->Height) {
- UnlockLayers(LockedLayerInfo);
- action = noaction;
- return 0;
- }
-
- /* Find out the offset for the clicked character, if any.
- ** This is the part that makes it special. Simple, isn't it. Hah!
- */
- {
- REGISTER SHORT found = 0;
- BltClear(TempRaster, 32L, 0L);
- xoff = 0;
- while ((xoff<(16-FontWidth)) && !found) {
- ClipBlit(&rp, xl+xoff, yt,
- &TempRp, 0L, 0L, (LONG)FontWidth, 16L, COPY);
- WaitBlit();
- yoff = 0;
- while ((yoff<(16-FontHeight)) && !found) {
- if (interpret(&TempRaster[yoff]) != 255) {
- found = 1;
- }
- ++yoff;
- }
- ++xoff;
- }
-
- /* Did we find a character? */
- if (!found) {
- /* No, back off */
- UnlockLayers(LockedLayerInfo);
- action = noaction;
- return 0;
- }
- }
-
- /* Ok, now we know where to look for chars.
- ** xoff and yoff is character position within our 16x16 bitmap.
- */
- xl = xl + xoff-1; /* Adjust x */
- yt = yt + yoff-1; /* Adjust y */
- /* Find out offsets within the window */
- xoff = xl % FontWidth;
- yoff = yt % FontHeight;
- /* Set bounds */
- minx = xoff;
- maxx = minx+((window->Width-minx-FontWidth
- -(window->Flags & BORDERLESS ? 0 : 2)
- -(window->Flags & WINDOWSIZING ? 12 : 0))/FontWidth)*FontWidth;
- /* Check bounds */
- if (xl>maxx) {
- UnlockLayers(LockedLayerInfo);
- action = noaction;
- return 0;
- }
- /* Set box dimensions */
- xr = xl;
- yb = yt;
- ox = xr;
- oy = yt;
-
- /* Select unit while starting */
- starting = 1;
-
- /* Starting unit is character or frame */
- Unit = StartUnit;
- OFType = 0L;
- update_frame();
-
- /* Get the state machine running */
- FOREVER {
- /* Wait for something to happen */
- REGISTER LONGBITS sig =
- Wait(movesignal|cancelsignal|donesignal|clicksignal|timersignal);
-
- if ((sig & timersignal) && (CrawlPtrn != 0xffff)) {
- crawl_frame(0L);
- }
-
- mx = (LONG)window->MouseX;
- if (mx<0) {
- mx = 0;
- }
- /* Calculate which edge is closest */
- if ((mx-xl) < (xr-mx)) {
- closex = closeleft;
- } else {
- closex = closeright;
- }
- /* Only interested in real char pos */
- mx = mx - ((mx-xoff) % FontWidth);
-
- my = (LONG)window->MouseY;
- if (my<0) {
- my = 0;
- }
- /* Calculate which row is closest */
- if ((my-yt) < (yb-my)) {
- closey = closetop;
- } else {
- closey = closebottom;
- }
- my = my - ((my-yoff) % FontHeight);
-
- /* Hey, it moves! It's alive!! */
- if ((sig & movesignal) && (action == snaptext)) {
- if (mx != ox || my != oy) { /* Something's happened */
- ExtendSelection();
- update_frame();
- starting = 0;
- ox = mx;
- oy = my;
- sig &= ~clicksignal;
- }
- }
-
- /* Ok, forget it... */
- if (sig & cancelsignal) {
- erase_frame();
- UnlockLayers(LockedLayerInfo);
- return 0;
- }
-
- /* Click */
- if ((sig & clicksignal) && (action == snaptext)) {
- /* Selecting unit */
- if (starting) {
- if (mx == ox && my == oy) {
- ChangeUnit();
- if (Unit == UNIT_CHAR) {
- ChangeUnit();
- }
- update_frame();
- } else if (Unit == UNIT_FRAME) {
- ChangeUnit();
- update_frame();
- }
- }
- if (mx != ox || my != oy) { /* Click in a new place */
- ExtendSelection();
- update_frame();
- starting = 0;
- ox = mx;
- oy = my;
- }
- }
-
- /* Finished */
- if (sig & donesignal) {
- erase_frame();
- return SnapChars();
- }
- }
- }
-
-