Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | not available | ||||||||||||
Proposed branch: | lp:~nha/widelands/fixes | ||||||||||||
Merge into: | lp:widelands | ||||||||||||
Diff against target: |
700 lines (+225/-79) 14 files modified
src/log.cc (+2/-2) src/log.h (+2/-0) src/logic/bob.cc (+0/-8) src/logic/bob.h (+7/-1) src/logic/immovable.cc (+25/-3) src/logic/immovable.h (+9/-0) src/logic/instances.cc (+3/-0) src/logic/map.cc (+2/-0) src/logic/soldier.cc (+64/-55) src/logic/worker.cc (+41/-9) src/logic/worker.h (+3/-0) src/ui_basic/editbox.cc (+58/-1) src/ui_basic/editbox.h (+2/-0) src/wlapplication.cc (+7/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~nha/widelands/fixes | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Widelands Developers | Pending | ||
Review via email: mp+22326@code.launchpad.net |
Commit message
Description of the change
Various small fixes and behavior changes that I suggest for merging after the release of build15.
To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote : | # |
Revision history for this message
Raul Ferriz (raul.ferriz) wrote : | # |
I have checked the code, but not try to compile and run. It is safe, some clean up and longer waiting checks for soldiers when waiting a signal.
The only but is that I think that this can break replays.
Revision history for this message
Nicolai Hähnle (nha) wrote : | # |
Yes, it does break replays. I don't think this is a problem, since we have never guaranteed compatibility of replays.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/log.cc' |
2 | --- src/log.cc 2010-03-27 23:50:23 +0000 |
3 | +++ src/log.cc 2010-04-13 18:44:39 +0000 |
4 | @@ -25,6 +25,8 @@ |
5 | |
6 | extern std::ostream & wout; |
7 | |
8 | +bool g_verbose = false; |
9 | + |
10 | void log(const char * const fmt, ...) { |
11 | char buffer[2048]; |
12 | va_list va; |
13 | @@ -33,8 +35,6 @@ |
14 | vsnprintf(buffer, sizeof(buffer), fmt, va); |
15 | va_end(va); |
16 | |
17 | - //TODO: use iostreams instead of vprintf because other parts of |
18 | - // Widelands use iostreams |
19 | wout << buffer; |
20 | wout.flush(); |
21 | } |
22 | |
23 | === modified file 'src/log.h' |
24 | --- src/log.h 2010-03-27 23:50:23 +0000 |
25 | +++ src/log.h 2010-04-13 18:44:39 +0000 |
26 | @@ -33,4 +33,6 @@ |
27 | // wout is either std::cout or specified logfile. |
28 | void log(const char *, ...) PRINTF_FORMAT(1, 2); |
29 | |
30 | +extern bool g_verbose; |
31 | + |
32 | #endif |
33 | |
34 | === modified file 'src/logic/bob.cc' |
35 | --- src/logic/bob.cc 2010-04-04 12:32:35 +0000 |
36 | +++ src/logic/bob.cc 2010-04-13 18:44:39 +0000 |
37 | @@ -692,10 +692,6 @@ |
38 | void Bob::movepath_update(Game & game, State & state) |
39 | { |
40 | if (get_signal().size()) { |
41 | - if (serial() == 3755) |
42 | - molog |
43 | - ("[movepath_update] signal '%s'; popping task\n", |
44 | - get_signal().c_str()); |
45 | return pop_task(game); |
46 | } |
47 | |
48 | @@ -919,10 +915,6 @@ |
49 | m_walkstart = game.get_gametime(); |
50 | m_walkend = m_walkstart + tdelta; |
51 | |
52 | - if (serial() == 3755) |
53 | - molog |
54 | - ("[start_walk]: changint position from (%i, %i) to (%i, %i)\n", |
55 | - get_position().x, get_position().y, newnode.x, newnode.y); |
56 | set_position(game, newnode); |
57 | set_animation(game, a); |
58 | |
59 | |
60 | === modified file 'src/logic/bob.h' |
61 | --- src/logic/bob.h 2010-04-03 16:44:44 +0000 |
62 | +++ src/logic/bob.h 2010-04-13 18:44:39 +0000 |
63 | @@ -323,11 +323,17 @@ |
64 | bool is_walking() {return m_walking != IDLE;} |
65 | |
66 | |
67 | + /** |
68 | + * This is a hack that should not be used, if possible. |
69 | + * It is only introduced here because profiling showed |
70 | + * that soldiers spend a lot of time in the node blocked check. |
71 | + */ |
72 | + Bob * get_next_on_field() const {return m_linknext;} |
73 | + |
74 | protected: |
75 | Bob(const Descr & descr); |
76 | virtual ~Bob(); |
77 | |
78 | - |
79 | private: |
80 | void do_act(Game &); |
81 | void do_pop_task(Game &); |
82 | |
83 | === modified file 'src/logic/immovable.cc' |
84 | --- src/logic/immovable.cc 2010-04-01 11:19:48 +0000 |
85 | +++ src/logic/immovable.cc 2010-04-13 18:44:39 +0000 |
86 | @@ -337,7 +337,8 @@ |
87 | m_anim (0), |
88 | m_program (0), |
89 | m_program_ptr (0), |
90 | -m_program_step(0) |
91 | +m_program_step(0), |
92 | +m_reserved_by_worker(false) |
93 | {} |
94 | |
95 | |
96 | @@ -471,6 +472,22 @@ |
97 | dst.drawanim(pos, m_anim, game.get_gametime() - m_animstart, 0); |
98 | } |
99 | |
100 | +/** |
101 | + * Returns whether this immovable was reserved by a worker. |
102 | + */ |
103 | +bool Immovable::is_reserved_by_worker() const |
104 | +{ |
105 | + return m_reserved_by_worker; |
106 | +} |
107 | + |
108 | +/** |
109 | + * Change whether this immovable is marked as reserved by a worker. |
110 | + */ |
111 | +void Immovable::set_reserved_by_worker(bool reserve) |
112 | +{ |
113 | + m_reserved_by_worker = reserve; |
114 | +} |
115 | + |
116 | |
117 | /* |
118 | ============================== |
119 | @@ -480,7 +497,7 @@ |
120 | ============================== |
121 | */ |
122 | |
123 | -#define IMMOVABLE_SAVEGAME_VERSION 2 |
124 | +#define IMMOVABLE_SAVEGAME_VERSION 3 |
125 | |
126 | void Immovable::Loader::load(FileRead & fr, uint8_t const version) |
127 | { |
128 | @@ -537,6 +554,9 @@ |
129 | } |
130 | |
131 | imm.m_program_step = fr.Signed32(); |
132 | + |
133 | + if (version >= 3) |
134 | + imm.m_reserved_by_worker = fr.Unsigned8(); |
135 | } |
136 | |
137 | void Immovable::Loader::load_pointers() |
138 | @@ -560,7 +580,7 @@ |
139 | void Immovable::save |
140 | (Editor_Game_Base & egbase, Map_Map_Object_Saver & mos, FileWrite & fw) |
141 | { |
142 | - // This is in front because it is required to obtain the descriptiong |
143 | + // This is in front because it is required to obtain the description |
144 | // necessary to create the Immovable |
145 | fw.Unsigned8(header_Immovable); |
146 | fw.Unsigned8(IMMOVABLE_SAVEGAME_VERSION); |
147 | @@ -586,6 +606,8 @@ |
148 | |
149 | fw.Unsigned32(m_program_ptr); |
150 | fw.Signed32(m_program_step); |
151 | + |
152 | + fw.Unsigned8(m_reserved_by_worker); |
153 | } |
154 | |
155 | Map_Object::Loader * Immovable::load |
156 | |
157 | === modified file 'src/logic/immovable.h' |
158 | --- src/logic/immovable.h 2010-02-28 18:40:36 +0000 |
159 | +++ src/logic/immovable.h 2010-04-13 18:44:39 +0000 |
160 | @@ -153,6 +153,9 @@ |
161 | return descr().get_owner_tribe(); |
162 | } |
163 | |
164 | + bool is_reserved_by_worker() const; |
165 | + void set_reserved_by_worker(bool reserve); |
166 | + |
167 | protected: |
168 | Coords m_position; |
169 | |
170 | @@ -163,6 +166,12 @@ |
171 | uint32_t m_program_ptr; ///< index of next instruction to execute |
172 | int32_t m_program_step; ///< time of next step |
173 | |
174 | + /** |
175 | + * Immovables like trees are reserved by a worker that is walking |
176 | + * towards them, so that e.g. two lumberjacks don't attempt to |
177 | + * work on the same tree simultaneously. |
178 | + */ |
179 | + bool m_reserved_by_worker; |
180 | |
181 | // Load/save support |
182 | protected: |
183 | |
184 | === modified file 'src/logic/instances.cc' |
185 | --- src/logic/instances.cc 2010-03-27 23:50:23 +0000 |
186 | +++ src/logic/instances.cc 2010-04-13 18:44:39 +0000 |
187 | @@ -437,6 +437,9 @@ |
188 | */ |
189 | void Map_Object::molog(char const * fmt, ...) const |
190 | { |
191 | + if (!g_verbose && !m_logsink) |
192 | + return; |
193 | + |
194 | va_list va; |
195 | char buffer[2048]; |
196 | |
197 | |
198 | === modified file 'src/logic/map.cc' |
199 | --- src/logic/map.cc 2010-04-03 16:44:44 +0000 |
200 | +++ src/logic/map.cc 2010-04-13 18:44:39 +0000 |
201 | @@ -1892,6 +1892,7 @@ |
202 | |
203 | // Recursively check integrity |
204 | void debug(uint32_t const node, char const * const str) { |
205 | +#if 0 |
206 | uint32_t l = node * 2 + 1; |
207 | uint32_t r = node * 2 + 2; |
208 | if (m_data[node]->heap_index != static_cast<int32_t>(node)) { |
209 | @@ -1912,6 +1913,7 @@ |
210 | } |
211 | debug(r, str); |
212 | } |
213 | +#endif |
214 | } |
215 | |
216 | private: |
217 | |
218 | === modified file 'src/logic/soldier.cc' |
219 | --- src/logic/soldier.cc 2010-04-04 12:32:35 +0000 |
220 | +++ src/logic/soldier.cc 2010-04-13 18:44:39 +0000 |
221 | @@ -781,7 +781,9 @@ |
222 | if (signal == "blocked") |
223 | // Wait before we try again. Note that this must come *after* |
224 | // we check for a battle |
225 | - return start_task_idle(game, get_animation("idle"), 250); |
226 | + // Note that we *should* be woken via sendSpaceSignals, |
227 | + // so the timeout is just an additional safety net. |
228 | + return start_task_idle(game, get_animation("idle"), 5000); |
229 | |
230 | if (!location) { |
231 | molog("[attack] our location disappeared during a battle\n"); |
232 | @@ -854,7 +856,7 @@ |
233 | (start_task_movepath |
234 | (game, |
235 | baseflag.get_position(), |
236 | - 0, |
237 | + 4, // use larger persist when returning home |
238 | descr().get_right_walk_anims(does_carry_ware()))) |
239 | return; |
240 | else { |
241 | @@ -870,7 +872,7 @@ |
242 | (start_task_movepath |
243 | (game, |
244 | enemy->base_flag().get_position(), |
245 | - 2, |
246 | + 3, |
247 | descr().get_right_walk_anims(does_carry_ware()))) |
248 | return; |
249 | else { |
250 | @@ -1015,7 +1017,9 @@ |
251 | if (signal == "blocked") |
252 | // Wait before we try again. Note that this must come *after* |
253 | // we check for a battle |
254 | - return start_task_idle(game, get_animation("idle"), 250); |
255 | + // Note that we *should* be woken via sendSpaceSignals, |
256 | + // so the timeout is just an additional safety net. |
257 | + return start_task_idle(game, get_animation("idle"), 5000); |
258 | |
259 | // If we only are defending our home ... |
260 | if (state.ivar1 & CF_DEFEND_STAYHOME) { |
261 | @@ -1103,7 +1107,7 @@ |
262 | (start_task_movepath |
263 | (game, |
264 | baseflag.get_position(), |
265 | - 0, |
266 | + 4, // use larger persist when returning home |
267 | descr().get_right_walk_anims(does_carry_ware()))) |
268 | return; |
269 | |
270 | @@ -1153,7 +1157,7 @@ |
271 | (start_task_movepath |
272 | (game, |
273 | target.s->get_position(), |
274 | - 1, |
275 | + 3, |
276 | descr().get_right_walk_anims(does_carry_ware()), |
277 | false, |
278 | 1)) |
279 | @@ -1506,62 +1510,67 @@ |
280 | bool Soldier::checkNodeBlocked |
281 | (Game & game, FCoords const & field, bool const commit) |
282 | { |
283 | - if (!isOnBattlefield()) |
284 | - return false; |
285 | - |
286 | - if (upcast(Building, building, get_location(game))) { |
287 | - if (field == building->get_position()) { |
288 | - if (commit) |
289 | - sendSpaceSignals(game); |
290 | - return false; // we can always walk home |
291 | - } |
292 | - } |
293 | - |
294 | - std::vector<Bob *> soldiers; |
295 | - game.map().find_bobs |
296 | - (Area<FCoords>(field, 0), &soldiers, FindBobSoldierOnBattlefield()); |
297 | + State * attackdefense = get_state(taskAttack); |
298 | + |
299 | + if (!attackdefense) |
300 | + attackdefense = get_state(taskDefense); |
301 | |
302 | if |
303 | - (soldiers.size() && |
304 | - (!m_battle || |
305 | - std::find(soldiers.begin(), soldiers.end(), m_battle->opponent(*this)) |
306 | - == |
307 | - soldiers.end())) |
308 | + (!attackdefense || |
309 | + (attackdefense->ivar1 & CF_RETREAT_WHEN_INJURED and |
310 | + attackdefense->ui32var3 > get_current_hitpoints())) |
311 | { |
312 | - if (commit && soldiers.size() == 1) { |
313 | - Soldier & soldier = ref_cast<Soldier, Bob>(*soldiers[0]); |
314 | - if (soldier.get_owner() != get_owner() && soldier.canBeChallenged()) { |
315 | + // Retreating or non-combatant soldiers act like normal bobs |
316 | + return Bob::checkNodeBlocked(game, field, commit); |
317 | + } |
318 | + |
319 | + if (field.field->get_immovable() && field.field->get_immovable() == get_location(game)) { |
320 | + if (commit) |
321 | + sendSpaceSignals(game); |
322 | + return false; // we can always walk home |
323 | + } |
324 | + |
325 | + Soldier * foundsoldier = 0; |
326 | + bool foundbattle = false; |
327 | + bool foundopponent = false; |
328 | + bool multiplesoldiers = false; |
329 | + |
330 | + for (Bob * bob = field.field->get_first_bob(); bob; bob = bob->get_next_on_field()) { |
331 | + if (upcast(Soldier, soldier, bob)) { |
332 | + if (!soldier->isOnBattlefield() || !soldier->get_current_hitpoints()) |
333 | + continue; |
334 | + |
335 | + if (!foundsoldier) { |
336 | + foundsoldier = soldier; |
337 | + } else { |
338 | + multiplesoldiers = true; |
339 | + } |
340 | + |
341 | + if (soldier->getBattle()) { |
342 | + foundbattle = true; |
343 | + |
344 | + if (m_battle && m_battle->opponent(*this) == soldier) |
345 | + foundopponent = true; |
346 | + } |
347 | + } |
348 | + } |
349 | + |
350 | + if (!foundopponent && (foundbattle || foundsoldier)) { |
351 | + if (commit && !foundbattle && !multiplesoldiers) { |
352 | + if (foundsoldier->get_owner() != get_owner() && foundsoldier->canBeChallenged()) { |
353 | molog |
354 | ("[checkNodeBlocked] attacking a soldier (%u)\n", |
355 | - soldier.serial()); |
356 | - new Battle(game, *this, soldier); |
357 | - } |
358 | - } |
359 | - |
360 | - /// Only battles block retreating soldiers |
361 | - State * state = 0; |
362 | - |
363 | - if (get_state(taskAttack)) { |
364 | - state = get_state(taskAttack); |
365 | - } |
366 | - if (get_state(taskDefense)) { |
367 | - state = get_state(taskDefense); |
368 | - } |
369 | - if (state) { |
370 | - if |
371 | - (state->ivar1 & CF_RETREAT_WHEN_INJURED and |
372 | - state->ui32var3 > get_current_hitpoints()) |
373 | - { |
374 | - // Retreating soldiers act like normal bobs |
375 | - return Bob::checkNodeBlocked(game, field, commit); |
376 | - } |
377 | - } |
378 | + foundsoldier->serial()); |
379 | + new Battle(game, *this, *foundsoldier); |
380 | + } |
381 | + } |
382 | + |
383 | return true; |
384 | + } else { |
385 | + if (commit) |
386 | + sendSpaceSignals(game); |
387 | + return false; |
388 | } |
389 | - |
390 | - if (commit) |
391 | - sendSpaceSignals(game); |
392 | - return false; |
393 | } |
394 | |
395 | |
396 | |
397 | === modified file 'src/logic/worker.cc' |
398 | --- src/logic/worker.cc 2010-03-21 20:09:51 +0000 |
399 | +++ src/logic/worker.cc 2010-04-13 18:44:39 +0000 |
400 | @@ -453,15 +453,18 @@ |
401 | |
402 | Map & map = game.map(); |
403 | Area<FCoords> area (map.get_fcoords(get_position()), 0); |
404 | - if (action.sparam1 == "immovable") |
405 | + if (action.sparam1 == "immovable") { |
406 | + bool found_reserved = false; |
407 | + |
408 | for (;; ++area.radius) { |
409 | if (action.iparam1 < area.radius) { |
410 | send_signal(game, "fail"); // no object found, cannot run program |
411 | pop_task(game); |
412 | - informPlayer |
413 | - (game, |
414 | - ref_cast<Building, PlayerImmovable>(*get_location(game)), |
415 | - Map_Object_Descr::get_attribute_name(action.iparam2)); |
416 | + if (!found_reserved) |
417 | + informPlayer |
418 | + (game, |
419 | + ref_cast<Building, PlayerImmovable>(*get_location(game)), |
420 | + Map_Object_Descr::get_attribute_name(action.iparam2)); |
421 | return true; |
422 | } |
423 | std::vector<ImmovableFound> list; |
424 | @@ -472,12 +475,21 @@ |
425 | map.find_reachable_immovables |
426 | (area, &list, cstep, FindImmovableAttribute(action.iparam2)); |
427 | |
428 | + for (int idx = list.size() - 1; idx >= 0; idx--) { |
429 | + if (upcast(Immovable, imm, list[idx].object)) { |
430 | + if (imm->is_reserved_by_worker()) { |
431 | + found_reserved = true; |
432 | + list.erase(list.begin() + idx); |
433 | + } |
434 | + } |
435 | + } |
436 | + |
437 | if (list.size()) { |
438 | - state.objvar1 = list[game.logic_rand() % list.size()].object; |
439 | + set_program_objvar(game, state, list[game.logic_rand() % list.size()].object); |
440 | break; |
441 | } |
442 | } |
443 | - else |
444 | + } else { |
445 | for (;; ++area.radius) { |
446 | if (action.iparam1 < area.radius) { |
447 | send_signal(game, "fail"); // no object found, cannot run program |
448 | @@ -497,10 +509,11 @@ |
449 | (area, &list, cstep, FindBobAttribute(action.iparam2)); |
450 | |
451 | if (list.size()) { |
452 | - state.objvar1 = list[game.logic_rand() % list.size()]; |
453 | + set_program_objvar(game, state, list[game.logic_rand() % list.size()]); |
454 | break; |
455 | } |
456 | } |
457 | + } |
458 | |
459 | ++state.ivar1; |
460 | schedule_act(game, 10); |
461 | @@ -1701,7 +1714,7 @@ |
462 | "program", |
463 | static_cast<Bob::Ptr>(&Worker::program_update), |
464 | 0, |
465 | - 0, |
466 | + static_cast<Bob::Ptr>(&Worker::program_pop), |
467 | false |
468 | }; |
469 | |
470 | @@ -1739,6 +1752,25 @@ |
471 | } |
472 | } |
473 | |
474 | +void Worker::program_pop(Game & game, State & state) |
475 | +{ |
476 | + set_program_objvar(game, state, 0); |
477 | +} |
478 | + |
479 | +void Worker::set_program_objvar(Game & game, State & state, Map_Object * obj) |
480 | +{ |
481 | + assert(state.task == &taskProgram); |
482 | + |
483 | + if (upcast(Immovable, imm, state.objvar1.get(game))) { |
484 | + imm->set_reserved_by_worker(false); |
485 | + } |
486 | + |
487 | + state.objvar1 = obj; |
488 | + |
489 | + if (upcast(Immovable, imm, obj)) { |
490 | + imm->set_reserved_by_worker(true); |
491 | + } |
492 | +} |
493 | |
494 | const Bob::Task Worker::taskGowarehouse = { |
495 | "gowarehouse", |
496 | |
497 | === modified file 'src/logic/worker.h' |
498 | --- src/logic/worker.h 2010-02-28 18:40:36 +0000 |
499 | +++ src/logic/worker.h 2010-04-13 18:44:39 +0000 |
500 | @@ -181,6 +181,8 @@ |
501 | |
502 | bool does_carry_ware() {return m_carried_item.is_set();} |
503 | |
504 | + void set_program_objvar(Game &, State &, Map_Object * obj); |
505 | + |
506 | public: |
507 | static const Task taskTransfer; |
508 | static const Task taskBuildingwork; |
509 | @@ -203,6 +205,7 @@ |
510 | void buildingwork_update(Game &, State &); |
511 | void return_update(Game &, State &); |
512 | void program_update(Game &, State &); |
513 | + void program_pop(Game &, State &); |
514 | void gowarehouse_update(Game &, State &); |
515 | void gowarehouse_signalimmediate |
516 | (Game &, |
517 | |
518 | === modified file 'src/ui_basic/editbox.cc' |
519 | --- src/ui_basic/editbox.cc 2010-03-27 23:50:23 +0000 |
520 | +++ src/ui_basic/editbox.cc 2010-04-13 18:44:39 +0000 |
521 | @@ -46,6 +46,9 @@ |
522 | /// Position of the caret. |
523 | uint32_t caret; |
524 | |
525 | + /// Current scrolling offset to the text anchor position, in pixels |
526 | + int32_t scrolloffset; |
527 | + |
528 | /// Alignment of the text. Vertical alignment is always centered. |
529 | Align align; |
530 | }; |
531 | @@ -69,8 +72,9 @@ |
532 | |
533 | m->id = id; |
534 | m->align = static_cast<Align>((_align & Align_Horizontal) | Align_VCenter); |
535 | + m->caret = 0; |
536 | + m->scrolloffset = 0; |
537 | // yes, use *signed* max as maximum length; just a small safe-guard. |
538 | - m->caret = 0; |
539 | m->maxLength = std::numeric_limits<int32_t>::max(); |
540 | |
541 | set_handle_mouse(true); |
542 | @@ -138,6 +142,7 @@ |
543 | if (m->caret > m->text.size()) |
544 | m->caret = m->text.size(); |
545 | |
546 | + check_caret(); |
547 | update(); |
548 | } |
549 | } |
550 | @@ -163,6 +168,8 @@ |
551 | _align = static_cast<Align>((_align & Align_Horizontal) | Align_VCenter); |
552 | if (_align != m->align) { |
553 | m->align = _align; |
554 | + m->scrolloffset = 0; |
555 | + check_caret(); |
556 | update(); |
557 | } |
558 | } |
559 | @@ -220,6 +227,7 @@ |
560 | while ((m->text[--m->caret] & 0xc0) == 0x80) |
561 | m->text.erase(m->text.begin() + m->caret); |
562 | m->text.erase(m->text.begin() + m->caret); |
563 | + check_caret(); |
564 | changed.call(); |
565 | changedid.call(m->id); |
566 | update(); |
567 | @@ -233,6 +241,7 @@ |
568 | for (uint32_t new_caret = m->caret;; m->caret = new_caret) |
569 | if (0 == new_caret or isspace(m->text[--new_caret])) |
570 | break; |
571 | + check_caret(); |
572 | update(); |
573 | } |
574 | return true; |
575 | @@ -250,6 +259,7 @@ |
576 | m->caret = new_caret; |
577 | break; |
578 | } |
579 | + check_caret(); |
580 | update(); |
581 | } |
582 | return true; |
583 | @@ -257,6 +267,7 @@ |
584 | case SDLK_HOME: |
585 | if (m->caret != 0) { |
586 | m->caret = 0; |
587 | + check_caret(); |
588 | update(); |
589 | } |
590 | return true; |
591 | @@ -264,6 +275,7 @@ |
592 | case SDLK_END: |
593 | if (m->caret != m->text.size()) { |
594 | m->caret = m->text.size(); |
595 | + check_caret(); |
596 | update(); |
597 | } |
598 | return true; |
599 | @@ -296,6 +308,7 @@ |
600 | (m->text.begin() + m->caret++, |
601 | ((code.unicode & 0x3f) | 0x80)); |
602 | } |
603 | + check_caret(); |
604 | changed.call(); |
605 | changedid.call(m->id); |
606 | update(); |
607 | @@ -354,6 +367,8 @@ |
608 | break; |
609 | } |
610 | |
611 | + pos.x += m->scrolloffset; |
612 | + |
613 | UI::g_fh->draw_string |
614 | (dst, |
615 | m_fontname, m_fontsize, m_fontcolor, UI_FONT_CLR_BG, |
616 | @@ -367,4 +382,46 @@ |
617 | std::numeric_limits<uint32_t>::max()); |
618 | } |
619 | |
620 | +/** |
621 | + * Check the caret's position and scroll it into view if necessary. |
622 | + */ |
623 | +void EditBox::check_caret() |
624 | +{ |
625 | + std::string leftstr(m->text, 0, m->caret); |
626 | + std::string rightstr(m->text, m->caret, std::string::npos); |
627 | + uint32_t leftw; |
628 | + uint32_t rightw; |
629 | + uint32_t tmp; |
630 | + |
631 | + UI::g_fh->get_size(m_fontname, m_fontsize, leftstr, leftw, tmp); |
632 | + UI::g_fh->get_size(m_fontname, m_fontsize, rightstr, rightw, tmp); |
633 | + |
634 | + int32_t caretpos; |
635 | + |
636 | + switch (m->align & Align_Horizontal) { |
637 | + case Align_HCenter: |
638 | + caretpos = (get_w() - static_cast<int32_t>(leftw + rightw)) / 2 + m->scrolloffset + leftw; |
639 | + break; |
640 | + case Align_Right: |
641 | + caretpos = get_w() - 4 + m->scrolloffset - rightw; |
642 | + break; |
643 | + default: |
644 | + caretpos = 4 + m->scrolloffset + leftw; |
645 | + break; |
646 | + } |
647 | + |
648 | + if (caretpos < 4) |
649 | + m->scrolloffset += 4 - caretpos + get_w()/5; |
650 | + else if (caretpos > get_w() - 4) |
651 | + m->scrolloffset -= caretpos - get_w() + 4 + get_w()/5; |
652 | + |
653 | + if ((m->align & Align_Horizontal) == Align_Left) { |
654 | + if (m->scrolloffset > 0) |
655 | + m->scrolloffset = 0; |
656 | + } else if ((m->align & Align_Horizontal) == Align_Right) { |
657 | + if (m->scrolloffset < 0) |
658 | + m->scrolloffset = 0; |
659 | + } |
660 | +} |
661 | + |
662 | } |
663 | |
664 | === modified file 'src/ui_basic/editbox.h' |
665 | --- src/ui_basic/editbox.h 2010-03-27 23:50:23 +0000 |
666 | +++ src/ui_basic/editbox.h 2010-04-13 18:44:39 +0000 |
667 | @@ -74,6 +74,8 @@ |
668 | RGBColor m_fontcolor; |
669 | |
670 | boost::scoped_ptr<EditBoxImpl> m; |
671 | + |
672 | + void check_caret(); |
673 | }; |
674 | |
675 | } |
676 | |
677 | === modified file 'src/wlapplication.cc' |
678 | --- src/wlapplication.cc 2010-04-12 09:11:24 +0000 |
679 | +++ src/wlapplication.cc 2010-04-13 18:44:39 +0000 |
680 | @@ -1116,6 +1116,12 @@ |
681 | m_commandline.erase("double"); |
682 | } |
683 | |
684 | + if (m_commandline.count("verbose")) { |
685 | + g_verbose = true; |
686 | + |
687 | + m_commandline.erase("verbose"); |
688 | + } |
689 | + |
690 | if (m_commandline.count("editor")) { |
691 | m_filename = m_commandline["editor"]; |
692 | if (m_filename.size() and *m_filename.rbegin() == '/') |
693 | @@ -1332,6 +1338,7 @@ |
694 | " testing)\n\n"); |
695 | #endif |
696 | #endif |
697 | + wout << _(" --verbose Enable verbose debug messages\n") << endl; |
698 | wout << _(" --help Show this help\n") << endl; |
699 | wout |
700 | << |
Nicolai, most of these are no brainers and i agree of merging them.
However about the reserved thing please see my comment on the bug report.