| 1 | /* $Id$ */ |
| 2 | /* |
| 3 | * Copyright (c) 2003 Ben Harris |
| 4 | * All rights reserved. |
| 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person |
| 7 | * obtaining a copy of this software and associated documentation |
| 8 | * files (the "Software"), to deal in the Software without |
| 9 | * restriction, including without limitation the rights to use, |
| 10 | * copy, modify, merge, publish, distribute, sublicense, and/or |
| 11 | * sell copies of the Software, and to permit persons to whom the |
| 12 | * Software is furnished to do so, subject to the following |
| 13 | * conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be |
| 16 | * included in all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR |
| 22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| 23 | * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 25 | * SOFTWARE. |
| 26 | */ |
| 27 | |
| 28 | #include <MacTypes.h> |
| 29 | #include <Lists.h> |
| 30 | #include <MacWindows.h> |
| 31 | #include <Quickdraw.h> |
| 32 | #include <Script.h> |
| 33 | #include <ToolUtils.h> |
| 34 | |
| 35 | #include <limits.h> |
| 36 | #include <string.h> |
| 37 | |
| 38 | #include "putty.h" |
| 39 | #include "mac.h" |
| 40 | #include "macresid.h" |
| 41 | #include "terminal.h" |
| 42 | |
| 43 | static void mac_draweventloggrowicon(Session *s); |
| 44 | static void mac_adjusteventlogscrollbar(Session *s); |
| 45 | static void mac_clickeventlog(WindowPtr, EventRecord *); |
| 46 | static void mac_activateeventlog(WindowPtr, EventRecord *); |
| 47 | static void mac_groweventlog(WindowPtr, EventRecord *); |
| 48 | static void mac_updateeventlog(WindowPtr); |
| 49 | static void mac_closeeventlog(WindowPtr); |
| 50 | |
| 51 | static void mac_createeventlog(Session *s) |
| 52 | { |
| 53 | Rect view; |
| 54 | ListBounds bounds = { 0, 0, 0, 1 }; /* 1 column, 0 rows */ |
| 55 | Point csize = { 0, 0 }; |
| 56 | GrafPtr saveport; |
| 57 | long fondsize; |
| 58 | WinInfo *wi; |
| 59 | |
| 60 | s->eventlog_window = GetNewWindow(wEventLog, NULL, (WindowPtr)-1); |
| 61 | wi = snew(WinInfo); |
| 62 | memset(wi, 0, sizeof(*wi)); |
| 63 | wi->s = s; |
| 64 | wi->wtype = wEventLog; |
| 65 | wi->click = &mac_clickeventlog; |
| 66 | wi->activate = &mac_activateeventlog; |
| 67 | wi->grow = &mac_groweventlog; |
| 68 | wi->update = &mac_updateeventlog; |
| 69 | wi->close = &mac_closeeventlog; |
| 70 | SetWRefCon(s->eventlog_window, (long)wi); |
| 71 | GetPort(&saveport); |
| 72 | SetPort((GrafPtr)GetWindowPort(s->eventlog_window)); |
| 73 | fondsize = GetScriptVariable(smRoman, smScriptSmallFondSize); |
| 74 | TextFont(HiWord(fondsize)); |
| 75 | TextSize(LoWord(fondsize)); |
| 76 | SetPort(saveport); |
| 77 | #if TARGET_API_MAC_CARBON |
| 78 | GetPortBounds(GetWindowPort(s->eventlog_window), &view); |
| 79 | #else |
| 80 | view = s->eventlog_window->portRect; |
| 81 | #endif |
| 82 | view.right -= 15; /* Scrollbar */ |
| 83 | s->eventlog = LNew(&view, &bounds, csize, 0, s->eventlog_window, |
| 84 | TRUE, TRUE, FALSE, TRUE); |
| 85 | mac_adjusteventlogscrollbar(s); |
| 86 | #if TARGET_API_MAC_CARBON |
| 87 | SetListSelectionFlags(s->eventlog, lExtendDrag | lNoDisjoint | lNoExtend); |
| 88 | #else |
| 89 | (*s->eventlog)->selFlags = lExtendDrag | lNoDisjoint | lNoExtend; |
| 90 | #endif |
| 91 | } |
| 92 | |
| 93 | void mac_freeeventlog(Session *s) |
| 94 | { |
| 95 | |
| 96 | if (s->eventlog != NULL) |
| 97 | LDispose(s->eventlog); |
| 98 | if (s->eventlog_window != NULL) { |
| 99 | sfree((WinInfo *)GetWRefCon(s->eventlog_window)); |
| 100 | DisposeWindow(s->eventlog_window); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | void logevent(void *frontend, const char *str) |
| 105 | { |
| 106 | Session *s = frontend; |
| 107 | ListBounds bounds, visible; |
| 108 | Cell cell = { 0, 0 }; |
| 109 | char timebuf[40]; |
| 110 | struct tm tm; |
| 111 | char *string; |
| 112 | |
| 113 | tm=ltime(); |
| 114 | strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t", &tm); |
| 115 | |
| 116 | string=snewn(strlen(timebuf) + strlen(str) +1, char); |
| 117 | strcpy(string, timebuf); |
| 118 | strcat(string, str); |
| 119 | |
| 120 | if (s->eventlog == NULL) |
| 121 | mac_createeventlog(s); |
| 122 | if (s->eventlog == NULL) |
| 123 | return; |
| 124 | |
| 125 | #if TARGET_API_MAC_CARBON |
| 126 | GetListDataBounds(s->eventlog, &bounds); |
| 127 | GetListVisibleCells(s->eventlog, &visible); |
| 128 | #else |
| 129 | bounds = (*s->eventlog)->dataBounds; |
| 130 | visible = (*s->eventlog)->visible; |
| 131 | #endif |
| 132 | |
| 133 | cell.v = bounds.bottom; |
| 134 | LAddRow(1, cell.v, s->eventlog); |
| 135 | LSetCell(string, strlen(string), cell, s->eventlog); |
| 136 | /* ">=" and "2" because there can be a blank cell below the last one. */ |
| 137 | if (visible.bottom >= bounds.bottom) |
| 138 | LScroll(0, 2, s->eventlog); |
| 139 | sfree(string); |
| 140 | } |
| 141 | |
| 142 | static void mac_draweventloggrowicon(Session *s) |
| 143 | { |
| 144 | Rect clip; |
| 145 | RgnHandle savergn; |
| 146 | |
| 147 | SetPort((GrafPtr)GetWindowPort(s->eventlog_window)); |
| 148 | /* |
| 149 | * Stop DrawGrowIcon giving us space for a horizontal scrollbar |
| 150 | * See Tech Note TB575 for details. |
| 151 | */ |
| 152 | #if TARGET_API_MAC_CARBON |
| 153 | GetPortBounds(GetWindowPort(s->eventlog_window), &clip); |
| 154 | #else |
| 155 | clip = s->eventlog_window->portRect; |
| 156 | #endif |
| 157 | clip.left = clip.right - 15; |
| 158 | savergn = NewRgn(); |
| 159 | GetClip(savergn); |
| 160 | ClipRect(&clip); |
| 161 | DrawGrowIcon(s->eventlog_window); |
| 162 | SetClip(savergn); |
| 163 | DisposeRgn(savergn); |
| 164 | } |
| 165 | |
| 166 | /* |
| 167 | * For some reason, LNew doesn't seem to respect the hasGrow |
| 168 | * parameter, so we hammer the scrollbar into shape ourselves. |
| 169 | */ |
| 170 | static void mac_adjusteventlogscrollbar(Session *s) |
| 171 | { |
| 172 | #if TARGET_API_MAC_CARBON |
| 173 | Rect winrect; |
| 174 | |
| 175 | GetPortBounds(GetWindowPort(s->eventlog_window), &winrect); |
| 176 | SizeControl(GetListVerticalScrollBar(s->eventlog), |
| 177 | 16, winrect.bottom - 13); |
| 178 | #else |
| 179 | SizeControl((*s->eventlog)->vScroll, |
| 180 | 16, s->eventlog_window->portRect.bottom - 13); |
| 181 | #endif |
| 182 | } |
| 183 | |
| 184 | void mac_clickeventlog(WindowPtr window, EventRecord *event) |
| 185 | { |
| 186 | Session *s = mac_windowsession(window); |
| 187 | Point mouse; |
| 188 | GrafPtr saveport; |
| 189 | |
| 190 | GetPort(&saveport); |
| 191 | SetPort((GrafPtr)GetWindowPort(window)); |
| 192 | mouse = event->where; |
| 193 | GlobalToLocal(&mouse); |
| 194 | LClick(mouse, event->modifiers, s->eventlog); |
| 195 | SetPort(saveport); |
| 196 | } |
| 197 | |
| 198 | static void mac_groweventlog(WindowPtr window, EventRecord *event) |
| 199 | { |
| 200 | Session *s = mac_windowsession(window); |
| 201 | Rect limits; |
| 202 | long grow_result; |
| 203 | #if TARGET_API_MAC_CARBON |
| 204 | Rect rect; |
| 205 | Point cellsize; |
| 206 | #else |
| 207 | GrafPtr saveport; |
| 208 | #endif |
| 209 | |
| 210 | SetRect(&limits, 15, 0, SHRT_MAX, SHRT_MAX); |
| 211 | grow_result = GrowWindow(window, event->where, &limits); |
| 212 | if (grow_result == 0) return; |
| 213 | SizeWindow(window, LoWord(grow_result), HiWord(grow_result), TRUE); |
| 214 | LSize(LoWord(grow_result) - 15, HiWord(grow_result), s->eventlog); |
| 215 | mac_adjusteventlogscrollbar(s); |
| 216 | /* We would use SetListCellSize in Carbon, but it's missing. */ |
| 217 | (*s->eventlog)->cellSize.h = LoWord(grow_result) - 15; |
| 218 | #if TARGET_API_MAC_CARBON |
| 219 | cellsize.h = LoWord(grow_result) - 15; |
| 220 | GetListViewBounds(s->eventlog, &rect); |
| 221 | InvalWindowRect(window, &rect); |
| 222 | #else |
| 223 | GetPort(&saveport); |
| 224 | SetPort(window); |
| 225 | InvalRect(&(*s->eventlog)->rView); |
| 226 | SetPort(saveport); |
| 227 | #endif |
| 228 | } |
| 229 | |
| 230 | static void mac_activateeventlog(WindowPtr window, EventRecord *event) |
| 231 | { |
| 232 | Session *s = mac_windowsession(window); |
| 233 | int active = (event->modifiers & activeFlag) != 0; |
| 234 | |
| 235 | LActivate(active, s->eventlog); |
| 236 | mac_draweventloggrowicon(s); |
| 237 | } |
| 238 | |
| 239 | static void mac_updateeventlog(WindowPtr window) |
| 240 | { |
| 241 | Session *s = mac_windowsession(window); |
| 242 | #if TARGET_API_MAC_CARBON |
| 243 | RgnHandle visrgn; |
| 244 | #endif |
| 245 | |
| 246 | SetPort((GrafPtr)GetWindowPort(window)); |
| 247 | BeginUpdate(window); |
| 248 | #if TARGET_API_MAC_CARBON |
| 249 | visrgn = NewRgn(); |
| 250 | GetPortVisibleRegion(GetWindowPort(window), visrgn); |
| 251 | LUpdate(visrgn, s->eventlog); |
| 252 | DisposeRgn(visrgn); |
| 253 | #else |
| 254 | LUpdate(window->visRgn, s->eventlog); |
| 255 | #endif |
| 256 | mac_draweventloggrowicon(s); |
| 257 | EndUpdate(window); |
| 258 | } |
| 259 | |
| 260 | static void mac_closeeventlog(WindowPtr window) |
| 261 | { |
| 262 | |
| 263 | HideWindow(window); |
| 264 | } |
| 265 | |
| 266 | void mac_showeventlog(Session *s) |
| 267 | { |
| 268 | |
| 269 | SelectWindow(s->eventlog_window); |
| 270 | ShowWindow(s->eventlog_window); |
| 271 | } |
| 272 | |
| 273 | /* |
| 274 | * Local Variables: |
| 275 | * c-file-style: "simon" |
| 276 | * End: |
| 277 | */ |