/*--- wvart.c ------------------------------------------- */ /* This file contains the window procedure for the Article Viewing window * for WinVn. */ #include "windows.h" #ifndef MAC #include "winundoc.h" #endif #include "WVglob.h" #include "WinVn.h" long find_article_by_subject (TypHeader far *headers,long artindex,long num_headers); int cursor_to_char_number (int X, int Y,TypDoc *DocPtr,TypBlock far **BlockPtr,TypLine far **LinePtr); void view_article_by_message_id (TypDoc *Doc, char far *article_request, long artindex); long find_article_by_subject (TypHeader far *headers, long artindex, long num_headers) { char far *subject = headers[artindex++].subject; do { if (lstrcmpi (headers[artindex].subject, subject) == 0) return (artindex); /* return the index */ } while (artindex++ < num_headers); return (-1); /* not found */ } /**************************************************************************** FUNCTION: WinVnArtWndProc(HWND, unsigned, WORD, LONG) PURPOSE: Processes messages ****************************************************************************/ long FAR PASCAL WinVnArtWndProc (hWnd, message, wParam, lParam) HWND hWnd; unsigned message; WPARAM wParam; LPARAM lParam; { FARPROC lpProcAbout; HMENU hMenu; PAINTSTRUCT ps; /* paint structure */ HDC hDC; /* handle to display context */ RECT myRect; /* selection rectangle */ HWND hWndView; HDC hDCView; TypDoc *ThisDoc; TypGroup far *GroupDoc; int ih, j; int found, X, Y, charnum; int imemo; int CtrlState; TypLine far *LinePtr, far * ArtLinePtr; TypBlock far *BlockPtr, far * ArtBlockPtr; HANDLE hBlock; char mybuf[MAXINTERNALLINE]; unsigned int Offset; int reply; int result; char far *cptr; char far *textptr; int textlen; TypLineID MyLineID; HANDLE header_handle; TypHeader * headers; long header_num; #ifdef MAC int vRef; #endif for (ih = 0, found = FALSE; !found && ih < MAXARTICLEWNDS; ih++) { if (ArticleDocs[ih].hDocWnd == hWnd) { found = TRUE; ThisDoc = &(ArticleDocs[ih]); } } if (!found) { ThisDoc = CommDoc; } switch (message) { case WM_ACTIVATE: case WM_SETFOCUS: if (wParam) { ActiveArticleDoc = ThisDoc; } /* fall through */ case WM_SYSCOMMAND: return (DefWindowProc (hWnd, message, wParam, lParam)); case WM_SIZE: GetClientRect (hWnd, &myRect); ThisDoc->ScXWidth = myRect.right; ThisDoc->ScYHeight = myRect.bottom; ThisDoc->ScYLines = (myRect.bottom - myRect.top - TopSpace) / ArtLineHeight; ThisDoc->ScXChars = (myRect.right - myRect.left - SideSpace) / ArtCharWidth; break; case WM_DESTROY: ThisDoc->InUse = FALSE; if (ThisDoc == CommDoc) { CommBusy = FALSE; CommDoc = (TypDoc *) NULL; } /* Clear the pointer in the line for this article in the */ /* group document. This pointer currently points */ /* to the current document, which we are wiping out */ /* with the destruction of this window. */ if (ThisDoc->ParentDoc) { LockLine (ThisDoc->ParentDoc->hParentBlock, ThisDoc->ParentDoc->ParentOffset, ThisDoc->ParentDoc->ParentLineID, &BlockPtr, &LinePtr); GroupDoc = (TypGroup far *) ((char far *) LinePtr + sizeof (TypLine)); header_handle = GroupDoc->header_handle; headers = (TypHeader *) ((char *) GlobalLock (header_handle) + sizeof(char *)) ; headers[ThisDoc->LastSeenLineID].ArtDoc = (TypDoc *) NULL; UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID); GlobalUnlock (header_handle); } /* Clear document */ FreeDoc (ThisDoc); /* If there's another article window, make it the active */ /* artcile window so we don't create a new one if the */ /* New Article flag is FALSE. */ for (j = MAXARTICLEWNDS - 1; j >= 0; j--) { if (ArticleDocs[j].InUse) { ActiveArticleDoc = &(ArticleDocs[j]); break; } } break; case WM_KEYDOWN: /* See if this key should be mapped to a scrolling event * for which we have programmed the mouse. If so, * construct the appropriate mouse call and call the mouse code. */ #ifndef MAC if (wParam == VK_F6) { NextWindow (ThisDoc); } else { CtrlState = GetKeyState (VK_CONTROL) < 0; for (j = 0; j < NUMKEYS; j++) { if (wParam == key2scroll[j].wVirtKey && CtrlState == key2scroll[j].CtlState) { SendMessage (hWnd, key2scroll[j].iMessage, key2scroll[j].wRequest, 0L); break; } } } #endif break; case WM_LBUTTONDBLCLK: X = LOWORD (lParam); Y = HIWORD (lParam); charnum = cursor_to_char_number (X,Y,ThisDoc,&BlockPtr,&LinePtr); if (charnum >= 0) { textlen = ((TypText far *) ((char far *) LinePtr + sizeof (TypLine)))->NameLen; textptr = (char far *) ((char far *) LinePtr + sizeof (TypLine) + sizeof (TypText) ); if (textlen) { /* find a message-id */ char far *start, far *end; for (start = textptr + charnum; start >= textptr; start--) if (*start == '<') break; for (end = textptr + charnum; end < (textptr + textlen); end++) if (*end == '>') break; if ((start >= textptr) && (end < (textptr + textlen))) { sprintf (str, "ARTICLE %.*Fs\r", (int) ((long) end - (long) start + 1), start); LockLine (ThisDoc->ParentDoc->hParentBlock, ThisDoc->ParentDoc->ParentOffset, ThisDoc->ParentDoc->ParentLineID, &BlockPtr, &LinePtr); GroupDoc = (TypGroup far *) ((char far *) LinePtr + sizeof (TypLine)); view_article_by_message_id (ThisDoc->ParentDoc, str, ThisDoc->LastSeenLineID); } } } break; case WM_VSCROLL: ScrollIt (ThisDoc, wParam, lParam); break; case WM_PAINT: { HANDLE hBlock; unsigned int Offset, MyLen, width; int VertLines, HorzChars; int EndofDoc = FALSE; int RangeHigh, CurPos; int RestX; char far *textptr; TypArticle far *MyArt; TypBlock far *BlockPtr; TypLine far *LinePtr; HANDLE hBlackBrush; DWORD MyColors[4], MyBack[4]; int MyColorMask = 1, PrevColorMask = MyColorMask; SIZE string_size; #ifdef MAC RECT myRect; POINT myPoint; #endif hDC = BeginPaint (hWnd, &ps); GetClientRect (hWnd, &myRect); SelectObject (hDC, hFontArt); VertLines = ThisDoc->ScYLines; HorzChars = ThisDoc->ScXChars; LockLine (ThisDoc->hCurTopScBlock, ThisDoc->TopScOffset, ThisDoc->TopScLineID, &BlockPtr, &LinePtr); /* Update the scroll bar thumb position. */ CurPos = ThisDoc->TopLineOrd; if (CurPos < 0) CurPos = 0; RangeHigh = ThisDoc->TotalLines - VertLines; if (RangeHigh < 0) RangeHigh = 0; SetScrollRange (hWnd, SB_VERT, 0, RangeHigh, FALSE); SetScrollPos (hWnd, SB_VERT, CurPos, TRUE); #ifdef MAC myRect.right = ThisDoc->DocClipRect.right; myRect.top = 0; myRect.bottom = ArtLineHeight; #endif /* Now paint this stuff on the screen for debugging. */ X = SideSpace; Y = StartPen; if (LinePtr->length != END_OF_BLOCK) do { MyLen = LinePtr->length - sizeof (TypLine) - sizeof (int) - 1; MyLen = ((TypText far *) ((char far *) LinePtr + sizeof (TypLine)))->NameLen; textptr = (char far *) LinePtr + sizeof (TypLine) + sizeof (TypText); /* Now write out the line. */ #if 1 GetTextExtentPoint (hDC, textptr, MyLen, &string_size); width = string_size.cx; #else width = ArtCharWidth * MyLen; #endif TextOut (hDC, X, Y, textptr, MyLen); #ifdef MAC GetPen (&myPoint); myRect.left = myPoint.h; FillRect (&myRect, white); myRect.top += ArtLineHeight; myRect.bottom += ArtLineHeight; #else RestX = X + width; PatBlt (hDC, RestX, Y, myRect.right - RestX, ArtLineHeight, PATCOPY); #endif #if 0 if (MyLen < HorzChars) { RestX = X + width; #if 0 TextOut (hDC, RestX, Y, Blanks, MAXINTERNALLINE); #endif PatBlt (hDC, RestX, Y, myRect.right - RestX, ArtLineHeight, PATCOPY); } #endif Y += ArtLineHeight; } while (--VertLines > 0 && NextLine (&BlockPtr, &LinePtr)); /* We've reached the end of the data to be displayed */ /* on this window. If there's more screen real estate */ /* left, just blank it out. */ #if !MAC PatBlt (hDC, 0, Y, myRect.right, myRect.bottom - Y, PATCOPY); #else /* myRect.top = myRect.top + ArtLineHeight; */ myRect.bottom = ThisDoc->DocClipRect.bottom; myRect.left = 0; EraseRect (&myRect); #endif #if 0 while (VertLines-- > -1) { TextOut (hDC, X, Y, Blanks, HorzChars); Y += ArtLineHeight; } #endif UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID); EndPaint (hWnd, &ps); break; } case WM_COMMAND: switch (wParam) { case IDM_EXIT: DestroyWindow (hWnd); break; case IDM_SAVE: if (strcmp (SaveArtFileName, "")) { SaveArtAppend = TRUE; MRRWriteDocument (ActiveArticleDoc, sizeof (TypText), SaveArtFileName, SaveArtvRef, SaveArtAppend); /* Should the 0 be sizeof(TypText) ? */ break; } else { goto saveas; } case IDM_SAVEAS: saveas:; #ifndef MAC if (DialogBox (hInst, "WinVnSaveArt", hWnd, lpfnWinVnSaveArtDlg)) { InvalidateRect (hWnd, NULL, TRUE); } #else result = MySaveAs (SaveArtFileName, &SaveArtvRef, &SaveArtAppend); if (result) { MRRWriteDocument (ActiveArticleDoc, sizeof (TypText), SaveArtFileName, SaveArtvRef, SaveArtAppend); } #endif break; case IDM_FIND_NEXT_SAME: case IDM_NEXT_ARTICLE: if (ThisDoc->ParentDoc) { LockLine (ThisDoc->ParentDoc->hParentBlock, ThisDoc->ParentDoc->ParentOffset, ThisDoc->ParentDoc->ParentLineID, &BlockPtr, &LinePtr); GroupDoc = (TypGroup far *) ((char far *) LinePtr + sizeof (TypLine)); if (wParam == IDM_FIND_NEXT_SAME) { header_handle = GroupDoc->header_handle; headers = (TypHeader far *) ((char *)GlobalLock (header_handle) + sizeof(char *)) ; header_num = find_article_by_subject (headers,ThisDoc->LastSeenLineID,GroupDoc->total_headers - 1); GlobalUnlock (header_handle); if (header_num >= 0) ViewArticle (ThisDoc->ParentDoc, header_num, TRUE); else MessageBox (hWnd, "No more articles", "That's all!", MB_OK); } else { if (GroupDoc) { if (ThisDoc->LastSeenLineID < (GroupDoc->total_headers - 1) ) ViewArticle (ThisDoc->ParentDoc, ThisDoc->LastSeenLineID + 1, TRUE); else MessageBox (hWnd, "No more articles", "That's all!", MB_OK); } else MessageBox (hWnd, "Sorry--you must have the group window around\n\for me to be able to find the next article", "Can't find next article", MB_OK); UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID); } } else MessageBox (hWnd, "That Group's window is gone. Reopen it.", "Error", MB_OK); break; case IDM_FOLLOWUP: CreatePostingWnd (ThisDoc, DOCTYPE_POSTING); break; case IDM_MAIL: CreatePostingWnd (ThisDoc, DOCTYPE_MAIL); break; case IDM_SEARCH: FindDoc = ThisDoc; if (DialogBox (hInst, "WinVnFind", hWnd, lpfnWinVnFindDlg)) { found = DoFind (TRUE); if (!found) { strcpy (mybuf, "\""); strcat (mybuf, FindDoc->SearchStr); strcat (mybuf, "\" not found."); MessageBox (hWnd, mybuf, "Not found", MB_OK); } } break; case IDM_SEARCH_NEXT: FindDoc = ThisDoc; if (strcmp (FindDoc->SearchStr, "")) { found = DoFind (FALSE); if (!found) { strcpy (mybuf, "\""); strcat (mybuf, FindDoc->SearchStr); strcat (mybuf, "\" not found."); MessageBox (hWnd, mybuf, "No more occurrences", MB_OK); } } break; } break; default: return (DefWindowProc (hWnd, message, wParam, lParam)); } return (0); }